* fix(devapp): point dev installer at DingTalk-Real-AI, drop the fork
install-devapp.sh / .ps1 and the robot quickstart still pulled the dev
binary + dingtalk-dev skill from wxianfeng/dingtalk-workspace-cli's
feat/dws-devapp fork branch. The dev-app work has since landed on main and
shipped in stable v1.0.42 under DingTalk-Real-AI, so the fork dependency is
obsolete.
- DEVAPP_REPO default: wxianfeng/... → DingTalk-Real-AI/...
- Bootstrap URLs in headers + quickstart: fork feat/dws-devapp → main.
- Drop "preview/prerelease" wording — releases are now stable; the
newest-release resolution still works either way.
- Quickstart China note now points at the standard install.sh Gitee
mirror (which carries dws dev in v1.0.42); install-devapp.sh pulls its
binary from github.com, so a gitee-raw script alone would not help China.
Verified: releases?per_page=1 on DingTalk-Real-AI resolves v1.0.42 and the
darwin/skills assets are present.
Note: docs/devapp-agent-install-guide.md is separately stale (describes the
old source-build flow + the pre-rename `dws devapp` command) and needs its
own rewrite — left out of this change.
* docs(devapp): rewrite agent install guide for binary install + `dws dev`
The guide was stale on two axes:
- It described the old source-build flow (clone the fork branch + go/make,
env vars DEVAPP_REPO_URL / DEVAPP_BRANCH / DEVAPP_SOURCE_DIR), but
install-devapp.sh now downloads a pre-built binary (curl + tar, no
git/go/make) from DingTalk-Real-AI.
- Every command used the pre-rename `dws devapp ...`; the command is now
`dws dev app ...`.
Rewrite against the real `dws dev` tree (verified from the binary):
- install: DingTalk-Real-AI binary installer + correct env (DEVAPP_REPO /
DEVAPP_VERSION / DWS_INSTALL_DIR / DWS_NO_SKILLS) + a China Gitee note.
- skill name corrected to `dingtalk-dev`.
- commands: `dws dev app {list,get,create,update,enable,disable,delete,
credentials,permission,member,robot,security,version,webapp,event}` with
real flags (--confirm-name, --scope-values, --user-ids, --redirect-urls,
--version-id/--confirmed-sensitive), async robot create via submit/result,
version publish gated by check-approval.
158 lines
5.9 KiB
Bash
Executable File
158 lines
5.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# Copyright 2026 Alibaba Group
|
|
# Licensed under the Apache License, Version 2.0
|
|
#
|
|
# One-command installer for dws dev — pre-built binary, no build tools.
|
|
# Downloads the dev binary + dingtalk-dev skill from the DingTalk-Real-AI GitHub Releases.
|
|
# Requires only curl + tar (no go / make / git).
|
|
#
|
|
# Usage:
|
|
# curl -fsSL https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install-devapp.sh | sh
|
|
#
|
|
# 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_INSTALL_DIR binary dir (default: ~/.local/bin)
|
|
# DWS_NO_SKILLS set 1 to skip the dev skill
|
|
set -eu
|
|
|
|
DEVAPP_REPO="${DEVAPP_REPO:-DingTalk-Real-AI/dingtalk-workspace-cli}"
|
|
DEVAPP_VERSION="${DEVAPP_VERSION:-}"
|
|
INSTALL_DIR="${DWS_INSTALL_DIR:-$HOME/.local/bin}"
|
|
NO_SKILLS="${DWS_NO_SKILLS:-0}"
|
|
SKILL_NAME="dingtalk-dev"
|
|
|
|
say() { printf ' %s\n' "$@"; }
|
|
err() { printf ' ❌ %s\n' "$@" >&2; exit 1; }
|
|
need_cmd() { command -v "$1" >/dev/null 2>&1 || err "Missing required command: $1"; }
|
|
|
|
need_cmd curl
|
|
|
|
detect_os() {
|
|
case "$(uname -s)" in
|
|
Linux*) echo linux ;;
|
|
Darwin*) echo darwin ;;
|
|
MINGW*|MSYS*|CYGWIN*) echo windows ;; # Git Bash / MSYS2 / Cygwin on Windows
|
|
*) err "Unsupported OS: $(uname -s). On native Windows use install-devapp.ps1." ;;
|
|
esac
|
|
}
|
|
|
|
detect_arch() {
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) echo amd64 ;;
|
|
arm64|aarch64) echo arm64 ;;
|
|
*) err "Unsupported architecture: $(uname -m)" ;;
|
|
esac
|
|
}
|
|
|
|
# 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).
|
|
# Prefer `gh` CLI (authenticated, 5 000 req/h) over raw curl (60 req/h, easily rate-limited).
|
|
resolve_version() {
|
|
[ -n "$DEVAPP_VERSION" ] && return 0
|
|
|
|
# Try gh CLI first (authenticated, much higher rate limit)
|
|
if command -v gh >/dev/null 2>&1; then
|
|
DEVAPP_VERSION="$(gh api "repos/${DEVAPP_REPO}/releases?per_page=1" --jq '.[0].tag_name' 2>/dev/null || true)"
|
|
[ -n "$DEVAPP_VERSION" ] && return 0
|
|
fi
|
|
|
|
# Fallback: unauthenticated curl (may be rate-limited)
|
|
_tmpfile="$(mktemp)"
|
|
_http_code="$(curl -sSL -o "$_tmpfile" -w '%{http_code}' "https://api.github.com/repos/${DEVAPP_REPO}/releases?per_page=1" 2>/dev/null || echo "000")"
|
|
|
|
if [ "$_http_code" = "403" ] || [ "$_http_code" = "429" ]; then
|
|
rm -f "$_tmpfile"
|
|
err "GitHub API rate limit hit (HTTP ${_http_code}). Install the GitHub CLI (gh) or set DEVAPP_VERSION explicitly."
|
|
fi
|
|
|
|
DEVAPP_VERSION="$(grep -m1 '"tag_name"' "$_tmpfile" | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')"
|
|
rm -f "$_tmpfile"
|
|
[ -n "$DEVAPP_VERSION" ] || err "No release found on ${DEVAPP_REPO}. Set DEVAPP_VERSION to a published release tag."
|
|
}
|
|
|
|
install_skill() {
|
|
bundle="$1" # extracted skills bundle dir
|
|
src=""
|
|
for c in "$bundle/multi/$SKILL_NAME" "$bundle/skills/multi/$SKILL_NAME" "$bundle/$SKILL_NAME"; do
|
|
[ -f "$c/SKILL.md" ] && src="$c" && break
|
|
done
|
|
[ -n "$src" ] || { say " (dingtalk-dev not found in skills bundle; skipped)"; return 0; }
|
|
|
|
# cache so `dws skill setup --mode multi` can find a source later
|
|
cache="$HOME/.dws/skills/multi/$SKILL_NAME"
|
|
rm -rf "$cache"; mkdir -p "$cache"; cp -R "$src/." "$cache/"
|
|
|
|
installed=0; idx=0
|
|
for agent_dir in \
|
|
.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
|
|
do
|
|
base="$HOME/$agent_dir"
|
|
if [ "$idx" -gt 0 ] && [ ! -e "$(dirname "$base")" ]; then idx=$((idx + 1)); continue; fi
|
|
dest="$base/$SKILL_NAME"; rm -rf "$dest"; mkdir -p "$dest"; cp -R "$src/." "$dest/"
|
|
installed=$((installed + 1)); idx=$((idx + 1))
|
|
done
|
|
say "✅ Skill dingtalk-dev → ${installed} agent dir(s)"
|
|
}
|
|
|
|
main() {
|
|
resolve_version
|
|
os="$(detect_os)"; arch="$(detect_arch)"
|
|
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT INT TERM
|
|
|
|
printf '\n'
|
|
say "dws dev installer (pre-built binary)"
|
|
say "Repo: ${DEVAPP_REPO}"
|
|
say "Version: ${DEVAPP_VERSION}"
|
|
say "Target: ${os}/${arch}"
|
|
printf '\n'
|
|
|
|
# 1) binary (already ad-hoc signed by CI; copy does not break the signature)
|
|
if [ "$os" = "windows" ]; then
|
|
asset="dws-windows-${arch}.zip"; binname="dws.exe"
|
|
else
|
|
asset="dws-${os}-${arch}.tar.gz"; binname="dws"
|
|
fi
|
|
say "⬇ Downloading ${asset} ..."
|
|
curl -fsSL "https://github.com/${DEVAPP_REPO}/releases/download/${DEVAPP_VERSION}/${asset}" -o "$tmp/$asset" \
|
|
|| err "Binary download failed — does release ${DEVAPP_VERSION} have ${asset}?"
|
|
if [ "$os" = "windows" ]; then
|
|
need_cmd unzip; unzip -q "$tmp/$asset" -d "$tmp"
|
|
else
|
|
need_cmd tar; tar -xzf "$tmp/$asset" -C "$tmp"
|
|
fi
|
|
[ -f "$tmp/$binname" ] || err "${binname} not found inside ${asset}"
|
|
mkdir -p "$INSTALL_DIR"
|
|
cp "$tmp/$binname" "$INSTALL_DIR/$binname"; chmod +x "$INSTALL_DIR/$binname" 2>/dev/null || true
|
|
say "✅ Binary → ${INSTALL_DIR}/${binname}"
|
|
|
|
# 2) dev skill from the release's skills bundle
|
|
if [ "$NO_SKILLS" != "1" ]; then
|
|
if curl -fsSL "https://github.com/${DEVAPP_REPO}/releases/download/${DEVAPP_VERSION}/dws-skills.zip" -o "$tmp/skills.zip" 2>/dev/null; then
|
|
mkdir -p "$tmp/sk"
|
|
if command -v unzip >/dev/null 2>&1; then unzip -q "$tmp/skills.zip" -d "$tmp/sk"; else tar -xf "$tmp/skills.zip" -C "$tmp/sk"; fi
|
|
say ""
|
|
install_skill "$tmp/sk"
|
|
else
|
|
say " (no dws-skills.zip in release ${DEVAPP_VERSION}; skill skipped)"
|
|
fi
|
|
fi
|
|
|
|
printf '\n'
|
|
say "🎉 Done. Next steps:"
|
|
say " dws version"
|
|
say " dws auth login"
|
|
say " dws dev --help --format json"
|
|
say " dws dev app list --format json"
|
|
printf '\n'
|
|
case ":$PATH:" in
|
|
*":$INSTALL_DIR:"*) ;;
|
|
*) say "Note: ${INSTALL_DIR} is not on \$PATH — add it so 'dws' is found." ;;
|
|
esac
|
|
}
|
|
|
|
main
|