@coocarecloud/openclaw 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install.cmd ADDED
@@ -0,0 +1,116 @@
1
+ @echo off
2
+ chcp 65001 >nul 2>&1
3
+ setlocal enabledelayedexpansion
4
+
5
+ :: OpenClaw 一键安装脚本 (Windows)
6
+ :: Usage: 直接双击运行,或在 PowerShell 中执行:
7
+ :: irm https://dl.qrj.ai/openclaw/install.cmd | cmd
8
+
9
+ echo.
10
+ echo ╔══════════════════════════════════════╗
11
+ echo ║ OpenClaw 一键安装 by 晴辰云 ║
12
+ echo ╚══════════════════════════════════════╝
13
+ echo.
14
+
15
+ set "INSTALL_DIR=%LOCALAPPDATA%\OpenClaw"
16
+ set "R2_BASE=https://dl.qrj.ai/openclaw-standalone"
17
+ set "PLATFORM=win-x64"
18
+
19
+ :: --- Get latest version ---
20
+ echo [INFO] 获取最新版本...
21
+ for /f "delims=" %%v in ('powershell -NoProfile -Command "(Invoke-RestMethod -Uri '%R2_BASE%/latest.json' -TimeoutSec 5).version" 2^>nul') do set "VERSION=%%v"
22
+
23
+ if "%VERSION%"=="" (
24
+ echo [WARN] R2 获取失败,尝试 GitHub...
25
+ for /f "delims=" %%v in ('powershell -NoProfile -Command "(Invoke-RestMethod -Uri 'https://api.github.com/repos/coocare/openclaw-standalone/releases/latest' -TimeoutSec 10).tag_name -replace 'v',''" 2^>nul') do set "VERSION=%%v"
26
+ )
27
+
28
+ if "%VERSION%"=="" (
29
+ echo [ERROR] 无法获取最新版本号。请检查网络连接。
30
+ echo 或手动下载: https://github.com/coocare/openclaw-standalone/releases
31
+ pause
32
+ exit /b 1
33
+ )
34
+
35
+ echo [INFO] 最新版本: %VERSION%
36
+
37
+ :: --- Download ---
38
+ set "ARCHIVE=openclaw-%VERSION%-win-x64.zip"
39
+ set "DOWNLOAD_URL=%R2_BASE%/%VERSION%/%ARCHIVE%"
40
+ set "TMP_FILE=%TEMP%\%ARCHIVE%"
41
+
42
+ echo [INFO] 下载安装包...
43
+ powershell -NoProfile -Command "try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri '%DOWNLOAD_URL%' -OutFile '%TMP_FILE%' -UseBasicParsing } catch { exit 1 }"
44
+
45
+ if errorlevel 1 (
46
+ echo [WARN] R2 下载失败,尝试 GitHub...
47
+ set "DOWNLOAD_URL=https://github.com/coocare/openclaw-standalone/releases/download/v%VERSION%/%ARCHIVE%"
48
+ powershell -NoProfile -Command "try { $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri '!DOWNLOAD_URL!' -OutFile '%TMP_FILE%' -UseBasicParsing } catch { exit 1 }"
49
+ )
50
+
51
+ if errorlevel 1 (
52
+ echo [ERROR] 下载失败。请检查网络连接。
53
+ pause
54
+ exit /b 1
55
+ )
56
+
57
+ echo [OK] 下载完成
58
+
59
+ :: --- Extract ---
60
+ echo [INFO] 解压到 %INSTALL_DIR% ...
61
+ if exist "%INSTALL_DIR%" rmdir /s /q "%INSTALL_DIR%"
62
+ mkdir "%INSTALL_DIR%" 2>nul
63
+
64
+ powershell -NoProfile -Command "Expand-Archive -Path '%TMP_FILE%' -DestinationPath '%INSTALL_DIR%' -Force"
65
+
66
+ :: Handle nested 'openclaw' directory from archive
67
+ if exist "%INSTALL_DIR%\openclaw\node.exe" (
68
+ powershell -NoProfile -Command "Get-ChildItem '%INSTALL_DIR%\openclaw\*' | Move-Item -Destination '%INSTALL_DIR%' -Force"
69
+ rmdir /s /q "%INSTALL_DIR%\openclaw" 2>nul
70
+ )
71
+
72
+ del "%TMP_FILE%" 2>nul
73
+ echo [OK] 解压完成
74
+
75
+ :: --- Verify ---
76
+ if not exist "%INSTALL_DIR%\openclaw.cmd" (
77
+ echo [ERROR] 解压后未找到 openclaw.cmd
78
+ pause
79
+ exit /b 1
80
+ )
81
+
82
+ :: --- Add to PATH ---
83
+ echo [INFO] 配置环境变量...
84
+ powershell -NoProfile -Command ^
85
+ "$userPath = [Environment]::GetEnvironmentVariable('Path', 'User'); " ^
86
+ "if ($userPath -notlike '*%INSTALL_DIR%*') { " ^
87
+ " [Environment]::SetEnvironmentVariable('Path', $userPath + ';%INSTALL_DIR%', 'User'); " ^
88
+ " Write-Host '[OK] 已添加到 PATH' " ^
89
+ "} else { " ^
90
+ " Write-Host '[INFO] PATH 已包含安装目录' " ^
91
+ "}"
92
+
93
+ :: Add to current session PATH too
94
+ set "PATH=%INSTALL_DIR%;%PATH%"
95
+
96
+ :: --- Verify version ---
97
+ echo.
98
+ "%INSTALL_DIR%\openclaw.cmd" --version 2>nul
99
+
100
+ :: --- Done ---
101
+ echo.
102
+ echo ╔══════════════════════════════════════╗
103
+ echo ║ ✅ OpenClaw 安装成功! ║
104
+ echo ╚══════════════════════════════════════╝
105
+ echo.
106
+ echo 安装目录: %INSTALL_DIR%
107
+ echo.
108
+ echo 请重新打开终端(PowerShell / CMD)使 PATH 生效,然后:
109
+ echo openclaw --help # 查看帮助
110
+ echo openclaw setup # 初始化配置
111
+ echo openclaw gateway # 启动 Gateway
112
+ echo.
113
+ echo 图形管理面板: https://github.com/coocare/clawpanel
114
+ echo AI 接口服务: https://gpt.qt.cool
115
+ echo.
116
+ pause
package/install.sh ADDED
@@ -0,0 +1,191 @@
1
+ #!/bin/bash
2
+ # OpenClaw 一键安装脚本 (macOS / Linux)
3
+ # Usage: curl -fsSL https://dl.qrj.ai/openclaw/install.sh | bash
4
+ # Or: curl -fsSL https://raw.githubusercontent.com/coocare/openclaw-standalone/main/install.sh | bash
5
+
6
+ set -euo pipefail
7
+
8
+ # --- Configuration ---
9
+ INSTALL_DIR="${OPENCLAW_HOME:-$HOME/.openclaw-bin}"
10
+ R2_BASE="https://dl.qrj.ai/openclaw-standalone"
11
+ GITHUB_BASE="https://github.com/coocare/openclaw-standalone/releases/download"
12
+
13
+ # --- Colors ---
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ CYAN='\033[0;36m'
18
+ NC='\033[0m'
19
+
20
+ info() { echo -e "${CYAN}[INFO]${NC} $*"; }
21
+ ok() { echo -e "${GREEN}[OK]${NC} $*"; }
22
+ warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
23
+ error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
24
+
25
+ # --- Detect platform ---
26
+ detect_platform() {
27
+ local os arch
28
+ os="$(uname -s)"
29
+ arch="$(uname -m)"
30
+
31
+ case "$os" in
32
+ Darwin) os="mac" ;;
33
+ Linux) os="linux" ;;
34
+ *) error "不支持的操作系统: $os" ;;
35
+ esac
36
+
37
+ case "$arch" in
38
+ x86_64|amd64) arch="x64" ;;
39
+ aarch64|arm64) arch="arm64" ;;
40
+ armv7l) arch="armv7l" ;;
41
+ *) error "不支持的架构: $arch" ;;
42
+ esac
43
+
44
+ echo "${os}-${arch}"
45
+ }
46
+
47
+ # --- Get latest version ---
48
+ get_latest_version() {
49
+ local version=""
50
+ # Try R2 first
51
+ if command -v curl &>/dev/null; then
52
+ version=$(curl -fsSL --connect-timeout 5 "$R2_BASE/latest.json" 2>/dev/null | \
53
+ grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | \
54
+ grep -o '"[^"]*"$' | tr -d '"') || true
55
+ fi
56
+ # Fallback: GitHub API
57
+ if [ -z "$version" ]; then
58
+ version=$(curl -fsSL --connect-timeout 5 \
59
+ "https://api.github.com/repos/coocare/openclaw-standalone/releases/latest" 2>/dev/null | \
60
+ grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | \
61
+ grep -o '"[^"]*"$' | tr -d '"v') || true
62
+ fi
63
+ if [ -z "$version" ]; then
64
+ error "无法获取最新版本号。请检查网络连接或手动下载安装。"
65
+ fi
66
+ echo "$version"
67
+ }
68
+
69
+ # --- Download with retry ---
70
+ download() {
71
+ local url="$1" dest="$2"
72
+ local max_retries=3 retry=0
73
+
74
+ while [ $retry -lt $max_retries ]; do
75
+ if curl -fSL --connect-timeout 10 --progress-bar -o "$dest" "$url" 2>&1; then
76
+ return 0
77
+ fi
78
+ retry=$((retry + 1))
79
+ warn "下载失败,正在重试 ($retry/$max_retries)..."
80
+ sleep 2
81
+ done
82
+ return 1
83
+ }
84
+
85
+ # --- Main ---
86
+ main() {
87
+ echo ""
88
+ echo -e "${CYAN}╔══════════════════════════════════════╗${NC}"
89
+ echo -e "${CYAN}║ OpenClaw 一键安装 by 晴辰云 ║${NC}"
90
+ echo -e "${CYAN}╚══════════════════════════════════════╝${NC}"
91
+ echo ""
92
+
93
+ PLATFORM=$(detect_platform)
94
+ info "检测到平台: $PLATFORM"
95
+
96
+ VERSION=$(get_latest_version)
97
+ info "最新版本: $VERSION"
98
+
99
+ ARCHIVE="openclaw-${VERSION}-${PLATFORM}.tar.gz"
100
+ DOWNLOAD_URL="${R2_BASE}/${VERSION}/${ARCHIVE}"
101
+ GITHUB_URL="${GITHUB_BASE}/v${VERSION}/${ARCHIVE}"
102
+ TMP_DIR=$(mktemp -d)
103
+ TMP_FILE="${TMP_DIR}/${ARCHIVE}"
104
+
105
+ info "下载安装包..."
106
+ if ! download "$DOWNLOAD_URL" "$TMP_FILE"; then
107
+ warn "R2 下载失败,尝试 GitHub..."
108
+ if ! download "$GITHUB_URL" "$TMP_FILE"; then
109
+ rm -rf "$TMP_DIR"
110
+ error "下载失败。请检查网络连接或手动下载:\n $GITHUB_URL"
111
+ fi
112
+ fi
113
+ ok "下载完成: $(du -h "$TMP_FILE" | cut -f1)"
114
+
115
+ # Extract
116
+ info "解压到 $INSTALL_DIR ..."
117
+ rm -rf "$INSTALL_DIR"
118
+ mkdir -p "$INSTALL_DIR"
119
+ tar -xzf "$TMP_FILE" -C "$INSTALL_DIR" --strip-components=1
120
+ rm -rf "$TMP_DIR"
121
+ ok "解压完成"
122
+
123
+ # Verify
124
+ if [ ! -x "$INSTALL_DIR/openclaw" ]; then
125
+ error "解压后未找到 openclaw 可执行文件"
126
+ fi
127
+
128
+ # Check version
129
+ INSTALLED_VER=$("$INSTALL_DIR/openclaw" --version 2>/dev/null | tail -1 || echo "unknown")
130
+ ok "已安装 OpenClaw: $INSTALLED_VER"
131
+
132
+ # --- Add to PATH ---
133
+ SHELL_NAME="$(basename "$SHELL" 2>/dev/null || echo "bash")"
134
+ PATH_LINE="export PATH=\"$INSTALL_DIR:\$PATH\""
135
+ ADDED_PATH=false
136
+
137
+ case "$SHELL_NAME" in
138
+ zsh)
139
+ RC_FILE="$HOME/.zshrc"
140
+ ;;
141
+ bash)
142
+ if [ -f "$HOME/.bash_profile" ]; then
143
+ RC_FILE="$HOME/.bash_profile"
144
+ else
145
+ RC_FILE="$HOME/.bashrc"
146
+ fi
147
+ ;;
148
+ fish)
149
+ RC_FILE="$HOME/.config/fish/config.fish"
150
+ PATH_LINE="set -gx PATH $INSTALL_DIR \$PATH"
151
+ ;;
152
+ *)
153
+ RC_FILE="$HOME/.profile"
154
+ ;;
155
+ esac
156
+
157
+ if [ -f "$RC_FILE" ] && grep -qF "$INSTALL_DIR" "$RC_FILE" 2>/dev/null; then
158
+ info "PATH 已包含 $INSTALL_DIR"
159
+ else
160
+ echo "" >> "$RC_FILE"
161
+ echo "# OpenClaw standalone" >> "$RC_FILE"
162
+ echo "$PATH_LINE" >> "$RC_FILE"
163
+ ADDED_PATH=true
164
+ ok "已添加到 PATH ($RC_FILE)"
165
+ fi
166
+
167
+ # --- Done ---
168
+ echo ""
169
+ echo -e "${GREEN}╔══════════════════════════════════════╗${NC}"
170
+ echo -e "${GREEN}║ ✅ OpenClaw 安装成功! ║${NC}"
171
+ echo -e "${GREEN}╚══════════════════════════════════════╝${NC}"
172
+ echo ""
173
+ echo " 安装目录: $INSTALL_DIR"
174
+ echo " 版本: $INSTALLED_VER"
175
+ echo ""
176
+ if [ "$ADDED_PATH" = true ]; then
177
+ echo -e " ${YELLOW}请执行以下命令使 PATH 生效:${NC}"
178
+ echo " source $RC_FILE"
179
+ echo ""
180
+ fi
181
+ echo " 快速开始:"
182
+ echo " openclaw --help # 查看帮助"
183
+ echo " openclaw setup # 初始化配置"
184
+ echo " openclaw gateway # 启动 Gateway"
185
+ echo ""
186
+ echo -e " 图形管理面板: ${CYAN}https://github.com/coocare/clawpanel${NC}"
187
+ echo -e " AI 接口服务: ${CYAN}https://gpt.qt.cool${NC}"
188
+ echo ""
189
+ }
190
+
191
+ main "$@"
@@ -0,0 +1,152 @@
1
+ ; OpenClaw Standalone Installer - Inno Setup Script
2
+ ; Produces a professional guided .exe installer for Windows
3
+ ; Compile: ISCC.exe /DAppVersion=x.y.z /DSourceDir=...\build\win-x64 /DOutputDir=...\output setup.iss
4
+
5
+ #ifndef AppVersion
6
+ #define AppVersion "0.0.0"
7
+ #endif
8
+
9
+ #ifndef SourceDir
10
+ #define SourceDir "..\build\win-x64"
11
+ #endif
12
+
13
+ #ifndef OutputDir
14
+ #define OutputDir "..\output"
15
+ #endif
16
+
17
+ [Setup]
18
+ AppId={{A7E3F2B1-9C4D-4E5F-B6A8-1D2E3F4A5B6C}
19
+ AppName=OpenClaw
20
+ AppVersion={#AppVersion}
21
+ AppVerName=OpenClaw {#AppVersion}
22
+ AppPublisher=软通酷越 (coocare)
23
+ AppPublisherURL=https://github.com/coocare/openclaw-standalone
24
+ AppSupportURL=https://github.com/coocare/openclaw-standalone/issues
25
+ AppUpdatesURL=https://github.com/coocare/openclaw-standalone/releases
26
+ DefaultDirName={autopf}\openclaw
27
+ DefaultGroupName=OpenClaw
28
+ AllowNoIcons=yes
29
+ LicenseFile=..\LICENSE
30
+ OutputDir={#OutputDir}
31
+ OutputBaseFilename=openclaw-{#AppVersion}-win-x64-setup
32
+ SetupIconFile=..\assets\openclaw.ico
33
+ Compression=lzma2/ultra64
34
+ SolidCompression=yes
35
+ WizardStyle=modern
36
+ PrivilegesRequired=lowest
37
+ PrivilegesRequiredOverridesAllowed=dialog
38
+ ChangesEnvironment=yes
39
+ ArchitecturesAllowed=x64compatible
40
+ ArchitecturesInstallIn64BitMode=x64compatible
41
+ UninstallDisplayIcon={app}\openclaw.cmd
42
+ VersionInfoCompany=coocare
43
+ VersionInfoDescription=openclaw - AI 智能体引擎
44
+ VersionInfoProductName=openclaw
45
+ MinVersion=10.0
46
+
47
+ [Languages]
48
+ Name: "english"; MessagesFile: "compiler:Default.isl"
49
+
50
+ [Messages]
51
+ BeveledLabel=coocare · OpenClaw Setup
52
+
53
+ [CustomMessages]
54
+ AddToPath=Add OpenClaw to PATH (recommended)
55
+ FinishMessage=OpenClaw installed!%n%nOpen a terminal and type openclaw to get started.%n%nGUI panel: https://github.com/coocare/clawpanel
56
+
57
+ [Tasks]
58
+ Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "Configuration:"; Flags: checkedonce
59
+
60
+ [Files]
61
+ Source: "{#SourceDir}\node.exe"; DestDir: "{app}"; Flags: ignoreversion
62
+ Source: "{#SourceDir}\openclaw.cmd"; DestDir: "{app}"; Flags: ignoreversion
63
+ Source: "{#SourceDir}\VERSION"; DestDir: "{app}"; Flags: ignoreversion
64
+ Source: "{#SourceDir}\node_modules\*"; DestDir: "{app}\node_modules"; Flags: ignoreversion recursesubdirs createallsubdirs
65
+
66
+ [Icons]
67
+ Name: "{group}\openclaw 终端"; Filename: "{cmd}"; Parameters: "/k ""{app}\openclaw.cmd"""; WorkingDir: "{userdocs}"; Comment: "打开 openclaw 终端"
68
+ Name: "{group}\卸载 openclaw"; Filename: "{uninstallexe}"
69
+
70
+ [Run]
71
+ Filename: "{cmd}"; Parameters: "/k echo openclaw {#AppVersion} 安装成功!输入 openclaw 开始使用。&& ""{app}\openclaw.cmd"" --version"; Description: "打开终端验证安装"; Flags: nowait postinstall skipifsilent unchecked
72
+
73
+ [UninstallDelete]
74
+ Type: filesandordirs; Name: "{app}\node_modules"
75
+ Type: files; Name: "{app}\node.exe"
76
+ Type: files; Name: "{app}\openclaw.cmd"
77
+ Type: files; Name: "{app}\VERSION"
78
+
79
+ [Code]
80
+ // Add/remove install directory from user PATH
81
+ procedure AddToUserPath(Dir: string);
82
+ var
83
+ OldPath: string;
84
+ begin
85
+ if not RegQueryStringValue(HKEY_CURRENT_USER,
86
+ 'Environment', 'Path', OldPath) then
87
+ OldPath := '';
88
+ if Pos(Uppercase(Dir), Uppercase(OldPath)) = 0 then
89
+ begin
90
+ if OldPath <> '' then
91
+ OldPath := OldPath + ';';
92
+ OldPath := OldPath + Dir;
93
+ RegWriteStringValue(HKEY_CURRENT_USER,
94
+ 'Environment', 'Path', OldPath);
95
+ end;
96
+ end;
97
+
98
+ procedure RemoveFromUserPath(Dir: string);
99
+ var
100
+ OldPath, NewPath, Item: string;
101
+ I: Integer;
102
+ begin
103
+ if not RegQueryStringValue(HKEY_CURRENT_USER,
104
+ 'Environment', 'Path', OldPath) then
105
+ Exit;
106
+ NewPath := '';
107
+ while Length(OldPath) > 0 do
108
+ begin
109
+ I := Pos(';', OldPath);
110
+ if I = 0 then
111
+ begin
112
+ Item := OldPath;
113
+ OldPath := '';
114
+ end else begin
115
+ Item := Copy(OldPath, 1, I - 1);
116
+ OldPath := Copy(OldPath, I + 1, Length(OldPath));
117
+ end;
118
+ Item := Trim(Item);
119
+ if (Length(Item) > 0) and (CompareText(Item, Dir) <> 0) then
120
+ begin
121
+ if NewPath <> '' then
122
+ NewPath := NewPath + ';';
123
+ NewPath := NewPath + Item;
124
+ end;
125
+ end;
126
+ RegWriteStringValue(HKEY_CURRENT_USER,
127
+ 'Environment', 'Path', NewPath);
128
+ end;
129
+
130
+ procedure CurStepChanged(CurStep: TSetupStep);
131
+ begin
132
+ if CurStep = ssPostInstall then
133
+ begin
134
+ if IsTaskSelected('addtopath') then
135
+ AddToUserPath(ExpandConstant('{app}'));
136
+ end;
137
+ end;
138
+
139
+ procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
140
+ begin
141
+ if CurUninstallStep = usPostUninstall then
142
+ RemoveFromUserPath(ExpandConstant('{app}'));
143
+ end;
144
+
145
+ // Notify Windows about PATH change
146
+ procedure BroadcastEnvironmentChange;
147
+ var
148
+ Dummy: Longint;
149
+ begin
150
+ // SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment')
151
+ // Inno Setup doesn't have direct access, but the PATH change takes effect on next terminal open
152
+ end;
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@coocarecloud/openclaw",
3
+ "version": "0.0.1",
4
+ "description": "**零依赖安装包** — 无需 Node.js,无需 npm,下载即用!",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/bddiudiu/openclaw-standalone-coocare.git"
12
+ },
13
+ "author": "adam",
14
+ "license": "ISC",
15
+ "bugs": {
16
+ "url": "https://github.com/bddiudiu/openclaw-standalone-coocare/issues"
17
+ },
18
+ "homepage": "https://github.com/bddiudiu/openclaw-standalone-coocare#readme"
19
+ }
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+ # OpenClaw Standalone - R2 旧版本清理脚本
3
+ # Usage: CLOUDFLARE_ACCOUNT_ID=xxx CLOUDFLARE_API_TOKEN=xxx bash scripts/cleanup-r2.sh [keep_count]
4
+ # Requires: wrangler CLI installed
5
+
6
+ set -euo pipefail
7
+
8
+ KEEP_COUNT="${1:-3}" # 保留最近 N 个版本,默认 3
9
+ BUCKET="clawpanel-releases"
10
+ PREFIX="openclaw-standalone/"
11
+
12
+ echo "=== OpenClaw Standalone R2 Cleanup ==="
13
+ echo "Bucket: $BUCKET"
14
+ echo "Prefix: $PREFIX"
15
+ echo "Keep latest: $KEEP_COUNT versions"
16
+ echo ""
17
+
18
+ # List all version directories
19
+ echo "Listing versions..."
20
+ VERSIONS=$(npx wrangler r2 object list "$BUCKET" --prefix "$PREFIX" 2>/dev/null | \
21
+ grep -oE '"key":"openclaw-standalone/[^/]+/' | \
22
+ grep -oE '[0-9]+\.[0-9]+\.[0-9]+[^/]*' | \
23
+ sort -Vr | uniq)
24
+
25
+ if [ -z "$VERSIONS" ]; then
26
+ echo "No versions found."
27
+ exit 0
28
+ fi
29
+
30
+ echo "Found versions:"
31
+ COUNT=0
32
+ while IFS= read -r ver; do
33
+ COUNT=$((COUNT + 1))
34
+ if [ $COUNT -le $KEEP_COUNT ]; then
35
+ echo " ✅ $ver (keep)"
36
+ else
37
+ echo " 🗑️ $ver (will delete)"
38
+ fi
39
+ done <<< "$VERSIONS"
40
+
41
+ # Delete old versions
42
+ COUNT=0
43
+ while IFS= read -r ver; do
44
+ COUNT=$((COUNT + 1))
45
+ if [ $COUNT -gt $KEEP_COUNT ]; then
46
+ echo ""
47
+ echo "Deleting $ver..."
48
+ # List and delete all objects under this version
49
+ npx wrangler r2 object list "$BUCKET" --prefix "${PREFIX}${ver}/" 2>/dev/null | \
50
+ grep -oE '"key":"[^"]*"' | grep -oE ':[^"]*"' | tr -d ':"' | \
51
+ while IFS= read -r key; do
52
+ echo " rm $key"
53
+ npx wrangler r2 object delete "$BUCKET/$key" 2>/dev/null || true
54
+ done
55
+ fi
56
+ done <<< "$VERSIONS"
57
+
58
+ echo ""
59
+ echo "=== Cleanup complete ==="