@leoqlin/openclaw-qqbot 1.6.7-alpha1
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/LICENSE +22 -0
- package/README.md +484 -0
- package/README.zh.md +479 -0
- package/bin/qqbot-cli.js +243 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +26 -0
- package/dist/src/admin-resolver.d.ts +33 -0
- package/dist/src/admin-resolver.js +157 -0
- package/dist/src/api.d.ts +301 -0
- package/dist/src/api.js +890 -0
- package/dist/src/channel.d.ts +29 -0
- package/dist/src/channel.js +452 -0
- package/dist/src/config.d.ts +56 -0
- package/dist/src/config.js +278 -0
- package/dist/src/credential-backup.d.ts +31 -0
- package/dist/src/credential-backup.js +66 -0
- package/dist/src/deliver-debounce.d.ts +74 -0
- package/dist/src/deliver-debounce.js +174 -0
- package/dist/src/gateway.d.ts +18 -0
- package/dist/src/gateway.js +2005 -0
- package/dist/src/group-history.d.ts +136 -0
- package/dist/src/group-history.js +226 -0
- package/dist/src/image-server.d.ts +87 -0
- package/dist/src/image-server.js +570 -0
- package/dist/src/inbound-attachments.d.ts +60 -0
- package/dist/src/inbound-attachments.js +248 -0
- package/dist/src/known-users.d.ts +100 -0
- package/dist/src/known-users.js +263 -0
- package/dist/src/message-gating.d.ts +53 -0
- package/dist/src/message-gating.js +107 -0
- package/dist/src/message-queue.d.ts +89 -0
- package/dist/src/message-queue.js +257 -0
- package/dist/src/onboarding.d.ts +10 -0
- package/dist/src/onboarding.js +203 -0
- package/dist/src/outbound-deliver.d.ts +48 -0
- package/dist/src/outbound-deliver.js +392 -0
- package/dist/src/outbound.d.ts +205 -0
- package/dist/src/outbound.js +938 -0
- package/dist/src/proactive.d.ts +170 -0
- package/dist/src/proactive.js +399 -0
- package/dist/src/ref-index-store.d.ts +101 -0
- package/dist/src/ref-index-store.js +298 -0
- package/dist/src/reply-dispatcher.d.ts +35 -0
- package/dist/src/reply-dispatcher.js +311 -0
- package/dist/src/request-context.d.ts +25 -0
- package/dist/src/request-context.js +37 -0
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.js +10 -0
- package/dist/src/session-store.d.ts +52 -0
- package/dist/src/session-store.js +254 -0
- package/dist/src/slash-commands.d.ts +77 -0
- package/dist/src/slash-commands.js +1866 -0
- package/dist/src/startup-greeting.d.ts +30 -0
- package/dist/src/startup-greeting.js +97 -0
- package/dist/src/streaming.d.ts +247 -0
- package/dist/src/streaming.js +899 -0
- package/dist/src/stt.d.ts +21 -0
- package/dist/src/stt.js +70 -0
- package/dist/src/tools/channel.d.ts +16 -0
- package/dist/src/tools/channel.js +234 -0
- package/dist/src/tools/remind.d.ts +2 -0
- package/dist/src/tools/remind.js +256 -0
- package/dist/src/types.d.ts +367 -0
- package/dist/src/types.js +17 -0
- package/dist/src/typing-keepalive.d.ts +27 -0
- package/dist/src/typing-keepalive.js +64 -0
- package/dist/src/update-checker.d.ts +36 -0
- package/dist/src/update-checker.js +171 -0
- package/dist/src/utils/audio-convert.d.ts +98 -0
- package/dist/src/utils/audio-convert.js +755 -0
- package/dist/src/utils/chunked-upload.d.ts +68 -0
- package/dist/src/utils/chunked-upload.js +341 -0
- package/dist/src/utils/file-utils.d.ts +61 -0
- package/dist/src/utils/file-utils.js +172 -0
- package/dist/src/utils/image-size.d.ts +51 -0
- package/dist/src/utils/image-size.js +234 -0
- package/dist/src/utils/media-send.d.ts +158 -0
- package/dist/src/utils/media-send.js +499 -0
- package/dist/src/utils/media-tags.d.ts +14 -0
- package/dist/src/utils/media-tags.js +165 -0
- package/dist/src/utils/payload.d.ts +112 -0
- package/dist/src/utils/payload.js +186 -0
- package/dist/src/utils/pkg-version.d.ts +5 -0
- package/dist/src/utils/pkg-version.js +61 -0
- package/dist/src/utils/platform.d.ts +137 -0
- package/dist/src/utils/platform.js +390 -0
- package/dist/src/utils/ssrf-guard.d.ts +25 -0
- package/dist/src/utils/ssrf-guard.js +91 -0
- package/dist/src/utils/text-parsing.d.ts +36 -0
- package/dist/src/utils/text-parsing.js +75 -0
- package/dist/src/utils/upload-cache.d.ts +34 -0
- package/dist/src/utils/upload-cache.js +93 -0
- package/index.ts +31 -0
- package/node_modules/@eshaz/web-worker/LICENSE +201 -0
- package/node_modules/@eshaz/web-worker/README.md +134 -0
- package/node_modules/@eshaz/web-worker/browser.js +17 -0
- package/node_modules/@eshaz/web-worker/cjs/browser.js +16 -0
- package/node_modules/@eshaz/web-worker/cjs/node.js +219 -0
- package/node_modules/@eshaz/web-worker/index.d.ts +4 -0
- package/node_modules/@eshaz/web-worker/node.js +223 -0
- package/node_modules/@eshaz/web-worker/package.json +54 -0
- package/node_modules/@wasm-audio-decoders/common/index.js +5 -0
- package/node_modules/@wasm-audio-decoders/common/package.json +36 -0
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderCommon.js +231 -0
- package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderWorker.js +129 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/README +67 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/build_puff.js +31 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.c +863 -0
- package/node_modules/@wasm-audio-decoders/common/src/puff/puff.h +35 -0
- package/node_modules/@wasm-audio-decoders/common/src/utilities.js +3 -0
- package/node_modules/@wasm-audio-decoders/common/types.d.ts +7 -0
- package/node_modules/mpg123-decoder/README.md +265 -0
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js +185 -0
- package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js.map +1 -0
- package/node_modules/mpg123-decoder/index.js +8 -0
- package/node_modules/mpg123-decoder/package.json +58 -0
- package/node_modules/mpg123-decoder/src/EmscriptenWasm.js +464 -0
- package/node_modules/mpg123-decoder/src/MPEGDecoder.js +200 -0
- package/node_modules/mpg123-decoder/src/MPEGDecoderWebWorker.js +21 -0
- package/node_modules/mpg123-decoder/types.d.ts +30 -0
- package/node_modules/silk-wasm/LICENSE +21 -0
- package/node_modules/silk-wasm/README.md +85 -0
- package/node_modules/silk-wasm/lib/index.cjs +16 -0
- package/node_modules/silk-wasm/lib/index.d.ts +70 -0
- package/node_modules/silk-wasm/lib/index.mjs +16 -0
- package/node_modules/silk-wasm/lib/silk.wasm +0 -0
- package/node_modules/silk-wasm/lib/utils.d.ts +4 -0
- package/node_modules/silk-wasm/package.json +39 -0
- package/node_modules/simple-yenc/.github/FUNDING.yml +1 -0
- package/node_modules/simple-yenc/.prettierignore +1 -0
- package/node_modules/simple-yenc/LICENSE +7 -0
- package/node_modules/simple-yenc/README.md +163 -0
- package/node_modules/simple-yenc/dist/esm.js +1 -0
- package/node_modules/simple-yenc/dist/index.js +1 -0
- package/node_modules/simple-yenc/package.json +50 -0
- package/node_modules/simple-yenc/rollup.config.js +27 -0
- package/node_modules/simple-yenc/src/simple-yenc.js +302 -0
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +528 -0
- package/node_modules/ws/lib/receiver.js +706 -0
- package/node_modules/ws/lib/sender.js +602 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +554 -0
- package/node_modules/ws/lib/websocket.js +1393 -0
- package/node_modules/ws/package.json +70 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/openclaw.plugin.json +17 -0
- package/package.json +70 -0
- package/preload.cjs +33 -0
- package/scripts/cleanup-legacy-plugins.sh +124 -0
- package/scripts/link-sdk-core.cjs +185 -0
- package/scripts/postinstall-link-sdk.js +126 -0
- package/scripts/proactive-api-server.ts +369 -0
- package/scripts/send-proactive.ts +293 -0
- package/scripts/set-markdown.sh +156 -0
- package/scripts/test-sendmedia.ts +116 -0
- package/scripts/upgrade-via-npm.ps1 +460 -0
- package/scripts/upgrade-via-npm.sh +652 -0
- package/scripts/upgrade-via-source.sh +1026 -0
- package/skills/qqbot-channel/SKILL.md +263 -0
- package/skills/qqbot-channel/references/api_references.md +521 -0
- package/skills/qqbot-media/SKILL.md +60 -0
- package/skills/qqbot-remind/SKILL.md +159 -0
- package/src/admin-resolver.ts +181 -0
- package/src/api.ts +1284 -0
- package/src/channel.ts +477 -0
- package/src/config.ts +347 -0
- package/src/credential-backup.ts +72 -0
- package/src/deliver-debounce.ts +229 -0
- package/src/gateway.ts +2245 -0
- package/src/group-history.ts +328 -0
- package/src/image-server.ts +675 -0
- package/src/inbound-attachments.ts +321 -0
- package/src/known-users.ts +353 -0
- package/src/message-gating.ts +190 -0
- package/src/message-queue.ts +352 -0
- package/src/onboarding.ts +274 -0
- package/src/openclaw-plugin-sdk.d.ts +587 -0
- package/src/outbound-deliver.ts +473 -0
- package/src/outbound.ts +1131 -0
- package/src/proactive.ts +530 -0
- package/src/ref-index-store.ts +412 -0
- package/src/reply-dispatcher.ts +334 -0
- package/src/request-context.ts +49 -0
- package/src/runtime.ts +14 -0
- package/src/session-store.ts +303 -0
- package/src/slash-commands.ts +2030 -0
- package/src/startup-greeting.ts +120 -0
- package/src/streaming.ts +1077 -0
- package/src/stt.ts +86 -0
- package/src/tools/channel.ts +281 -0
- package/src/tools/remind.ts +308 -0
- package/src/types.ts +391 -0
- package/src/typing-keepalive.ts +59 -0
- package/src/update-checker.ts +186 -0
- package/src/utils/audio-convert.ts +859 -0
- package/src/utils/chunked-upload.ts +483 -0
- package/src/utils/file-utils.ts +193 -0
- package/src/utils/image-size.ts +266 -0
- package/src/utils/media-send.ts +631 -0
- package/src/utils/media-tags.ts +183 -0
- package/src/utils/payload.ts +265 -0
- package/src/utils/pkg-version.ts +64 -0
- package/src/utils/platform.ts +435 -0
- package/src/utils/ssrf-guard.ts +102 -0
- package/src/utils/text-parsing.ts +85 -0
- package/src/utils/upload-cache.ts +128 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# qqbot upgrade via npm package (Windows PowerShell)
|
|
2
|
+
#
|
|
3
|
+
# Windows-native equivalent of upgrade-via-npm.sh.
|
|
4
|
+
# No bash / Git Bash / WSL required.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# .\upgrade-via-npm.ps1 # upgrade to latest (default)
|
|
8
|
+
# .\upgrade-via-npm.ps1 -Version <version> # upgrade to specific version
|
|
9
|
+
# .\upgrade-via-npm.ps1 -SelfVersion # upgrade to local package.json version
|
|
10
|
+
# .\upgrade-via-npm.ps1 -AppId <appid> -Secret <secret> # configure on first install
|
|
11
|
+
# .\upgrade-via-npm.ps1 -NoRestart # file replacement only (for hot-upgrade)
|
|
12
|
+
|
|
13
|
+
param(
|
|
14
|
+
[string]$Version = "",
|
|
15
|
+
[switch]$SelfVersion,
|
|
16
|
+
[string]$AppId = "",
|
|
17
|
+
[string]$Secret = "",
|
|
18
|
+
[switch]$NoRestart,
|
|
19
|
+
[string]$Tag = "",
|
|
20
|
+
[string]$Pkg = "",
|
|
21
|
+
[switch]$Help
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
$ErrorActionPreference = "Stop"
|
|
25
|
+
$PKG_NAME = "@tencent-connect/openclaw-qqbot"
|
|
26
|
+
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
|
27
|
+
$PROJECT_DIR = Split-Path -Parent $SCRIPT_DIR
|
|
28
|
+
|
|
29
|
+
# -Pkg 覆盖包名(支持 "scope/name" 自动补 @)
|
|
30
|
+
if ($Pkg) {
|
|
31
|
+
$Pkg = $Pkg.Trim()
|
|
32
|
+
if (-not $Pkg.StartsWith("@")) { $Pkg = "@$Pkg" }
|
|
33
|
+
$PKG_NAME = $Pkg
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Read local version
|
|
37
|
+
$LOCAL_VERSION = ""
|
|
38
|
+
try {
|
|
39
|
+
$pkgPath = Join-Path $PROJECT_DIR "package.json"
|
|
40
|
+
if (Test-Path $pkgPath) {
|
|
41
|
+
$pkg = Get-Content $pkgPath -Raw | ConvertFrom-Json
|
|
42
|
+
$LOCAL_VERSION = $pkg.version
|
|
43
|
+
}
|
|
44
|
+
} catch {}
|
|
45
|
+
|
|
46
|
+
if ($Help) {
|
|
47
|
+
Write-Host "Usage:"
|
|
48
|
+
Write-Host " .\upgrade-via-npm.ps1 # upgrade to latest (default)"
|
|
49
|
+
Write-Host " .\upgrade-via-npm.ps1 -Version [version] # upgrade to specific version"
|
|
50
|
+
Write-Host " .\upgrade-via-npm.ps1 -SelfVersion # upgrade to repo version ($LOCAL_VERSION)"
|
|
51
|
+
Write-Host ""
|
|
52
|
+
Write-Host " -Pkg [scope/name] Custom npm package (e.g. ryantest/openclaw-qqbot)"
|
|
53
|
+
Write-Host " -AppId [appid] QQ bot appid (required on first install)"
|
|
54
|
+
Write-Host " -Secret [secret] QQ bot secret (required on first install)"
|
|
55
|
+
exit 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Determine install source
|
|
59
|
+
$INSTALL_SRC = ""
|
|
60
|
+
if ($Tag) {
|
|
61
|
+
$INSTALL_SRC = "${PKG_NAME}@${Tag}"
|
|
62
|
+
} elseif ($Version) {
|
|
63
|
+
$INSTALL_SRC = "${PKG_NAME}@${Version}"
|
|
64
|
+
} elseif ($SelfVersion) {
|
|
65
|
+
if (-not $LOCAL_VERSION) {
|
|
66
|
+
Write-Host "[ERROR] Cannot read version from package.json" -ForegroundColor Red
|
|
67
|
+
exit 1
|
|
68
|
+
}
|
|
69
|
+
$INSTALL_SRC = "${PKG_NAME}@${LOCAL_VERSION}"
|
|
70
|
+
} else {
|
|
71
|
+
$INSTALL_SRC = "${PKG_NAME}@latest"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Environment variable fallback
|
|
75
|
+
if (-not $AppId) { $AppId = $env:QQBOT_APPID }
|
|
76
|
+
if (-not $Secret) { $Secret = $env:QQBOT_SECRET }
|
|
77
|
+
if ((-not $AppId) -and (-not $Secret) -and $env:QQBOT_TOKEN) {
|
|
78
|
+
$parts = $env:QQBOT_TOKEN -split ":", 2
|
|
79
|
+
$AppId = $parts[0]
|
|
80
|
+
$Secret = $parts[1]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Detect CLI
|
|
84
|
+
$CMD = ""
|
|
85
|
+
foreach ($name in @("openclaw", "clawdbot", "moltbot")) {
|
|
86
|
+
try {
|
|
87
|
+
$null = Get-Command $name -ErrorAction Stop
|
|
88
|
+
$CMD = $name
|
|
89
|
+
break
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
if (-not $CMD) {
|
|
93
|
+
Write-Host "[ERROR] openclaw / clawdbot / moltbot not found" -ForegroundColor Red
|
|
94
|
+
exit 1
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
$HOME_DIR = $env:USERPROFILE
|
|
98
|
+
if (-not $HOME_DIR) { $HOME_DIR = [Environment]::GetFolderPath("UserProfile") }
|
|
99
|
+
$EXTENSIONS_DIR = Join-Path (Join-Path $HOME_DIR ".$CMD") "extensions"
|
|
100
|
+
|
|
101
|
+
Write-Host "==========================================="
|
|
102
|
+
Write-Host " qqbot npm upgrade: $INSTALL_SRC"
|
|
103
|
+
Write-Host "==========================================="
|
|
104
|
+
Write-Host ""
|
|
105
|
+
|
|
106
|
+
# [1/3] Download and extract new version
|
|
107
|
+
Write-Host "[1/5] Downloading new version..."
|
|
108
|
+
$TMPDIR_PACK = Join-Path ([System.IO.Path]::GetTempPath()) "qqbot-pack-$([guid]::NewGuid().ToString('N').Substring(0,8))"
|
|
109
|
+
$EXTRACT_DIR = Join-Path ([System.IO.Path]::GetTempPath()) "qqbot-extract-$([guid]::NewGuid().ToString('N').Substring(0,8))"
|
|
110
|
+
New-Item -ItemType Directory -Path $TMPDIR_PACK -Force | Out-Null
|
|
111
|
+
New-Item -ItemType Directory -Path $EXTRACT_DIR -Force | Out-Null
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
Push-Location $TMPDIR_PACK
|
|
115
|
+
|
|
116
|
+
# Multi-registry fallback
|
|
117
|
+
$PACK_OK = $false
|
|
118
|
+
$registries = @("https://registry.npmjs.org/", "https://registry.npmmirror.com/", "")
|
|
119
|
+
foreach ($registry in $registries) {
|
|
120
|
+
try {
|
|
121
|
+
if ($registry) {
|
|
122
|
+
Write-Host " Trying registry: $registry"
|
|
123
|
+
& npm pack $INSTALL_SRC --registry $registry --quiet 2>&1 | Out-Null
|
|
124
|
+
} else {
|
|
125
|
+
Write-Host " Trying default registry..."
|
|
126
|
+
& npm pack $INSTALL_SRC --quiet 2>&1 | Out-Null
|
|
127
|
+
}
|
|
128
|
+
if ($LASTEXITCODE -eq 0) {
|
|
129
|
+
$PACK_OK = $true
|
|
130
|
+
break
|
|
131
|
+
}
|
|
132
|
+
} catch {}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (-not $PACK_OK) {
|
|
136
|
+
Write-Host "[ERROR] npm pack failed (all registries unavailable)" -ForegroundColor Red
|
|
137
|
+
exit 1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
$TGZ_FILE = Get-ChildItem -Path $TMPDIR_PACK -Filter "*.tgz" | Select-Object -First 1
|
|
141
|
+
if (-not $TGZ_FILE) {
|
|
142
|
+
Write-Host "[ERROR] Downloaded tgz file not found" -ForegroundColor Red
|
|
143
|
+
exit 1
|
|
144
|
+
}
|
|
145
|
+
Write-Host " Downloaded: $($TGZ_FILE.Name)"
|
|
146
|
+
|
|
147
|
+
# Extract tgz (tar is built-in on Windows 10+)
|
|
148
|
+
& tar xzf $TGZ_FILE.FullName -C $EXTRACT_DIR
|
|
149
|
+
$PACKAGE_DIR = Join-Path $EXTRACT_DIR "package"
|
|
150
|
+
if (-not (Test-Path $PACKAGE_DIR)) {
|
|
151
|
+
Write-Host "[ERROR] Extraction failed, package directory not found" -ForegroundColor Red
|
|
152
|
+
exit 1
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
Pop-Location
|
|
156
|
+
|
|
157
|
+
# Prepare staging directory
|
|
158
|
+
$STAGING_DIR = Join-Path (Split-Path $EXTENSIONS_DIR -Parent) ".qqbot-upgrade-staging"
|
|
159
|
+
if (Test-Path $STAGING_DIR) { Remove-Item -Recurse -Force $STAGING_DIR }
|
|
160
|
+
Copy-Item -Recurse -Force $PACKAGE_DIR $STAGING_DIR
|
|
161
|
+
|
|
162
|
+
# Check bundled dependencies
|
|
163
|
+
$nmDir = Join-Path $STAGING_DIR "node_modules"
|
|
164
|
+
if (Test-Path $nmDir) {
|
|
165
|
+
$bundledCount = (Get-ChildItem -Directory $nmDir -ErrorAction SilentlyContinue | Measure-Object).Count
|
|
166
|
+
# Count scoped packages
|
|
167
|
+
Get-ChildItem -Directory $nmDir -Filter "@*" -ErrorAction SilentlyContinue | ForEach-Object {
|
|
168
|
+
$bundledCount += (Get-ChildItem -Directory $_.FullName -ErrorAction SilentlyContinue | Measure-Object).Count - 1
|
|
169
|
+
}
|
|
170
|
+
Write-Host " Bundled dependencies ready (${bundledCount} packages)"
|
|
171
|
+
} else {
|
|
172
|
+
Write-Host " [WARN] Bundled node_modules not found, installing dependencies..."
|
|
173
|
+
Push-Location $STAGING_DIR
|
|
174
|
+
try { & npm install --omit=dev --omit=peer --ignore-scripts --quiet 2>&1 | Out-Null } catch {}
|
|
175
|
+
Pop-Location
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
} finally {
|
|
179
|
+
# Clean up temp files
|
|
180
|
+
if (Test-Path $TMPDIR_PACK) { Remove-Item -Recurse -Force $TMPDIR_PACK -ErrorAction SilentlyContinue }
|
|
181
|
+
if (Test-Path $EXTRACT_DIR) { Remove-Item -Recurse -Force $EXTRACT_DIR -ErrorAction SilentlyContinue }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# ── Preflight: validate new package before writing to extensions ──
|
|
185
|
+
Write-Host ""
|
|
186
|
+
Write-Host "[2/5] Preflight checks..."
|
|
187
|
+
$PreflightOK = $true
|
|
188
|
+
|
|
189
|
+
# (a) package.json exists and has version
|
|
190
|
+
$StagingPkg = Join-Path $STAGING_DIR "package.json"
|
|
191
|
+
$StagingVersion = ""
|
|
192
|
+
if (-not (Test-Path $StagingPkg)) {
|
|
193
|
+
Write-Host " [FAIL] New package missing package.json" -ForegroundColor Red
|
|
194
|
+
$PreflightOK = $false
|
|
195
|
+
} else {
|
|
196
|
+
try {
|
|
197
|
+
$spkg = Get-Content $StagingPkg -Raw | ConvertFrom-Json
|
|
198
|
+
$StagingVersion = $spkg.version
|
|
199
|
+
if (-not $StagingVersion) { throw "no version" }
|
|
200
|
+
Write-Host " [OK] Version: $StagingVersion"
|
|
201
|
+
} catch {
|
|
202
|
+
Write-Host " [FAIL] package.json unreadable or missing version" -ForegroundColor Red
|
|
203
|
+
$PreflightOK = $false
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# (b) Entry file exists
|
|
208
|
+
$EntryFile = ""
|
|
209
|
+
foreach ($candidate in @("dist\index.js", "index.js")) {
|
|
210
|
+
if (Test-Path (Join-Path $STAGING_DIR $candidate)) {
|
|
211
|
+
$EntryFile = $candidate
|
|
212
|
+
break
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (-not $EntryFile) {
|
|
216
|
+
Write-Host " [FAIL] Missing entry file (dist\index.js or index.js)" -ForegroundColor Red
|
|
217
|
+
$PreflightOK = $false
|
|
218
|
+
} else {
|
|
219
|
+
Write-Host " [OK] Entry file: $EntryFile"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# (c) Core directory dist/src
|
|
223
|
+
$CoreSrcDir = Join-Path $STAGING_DIR "dist" "src"
|
|
224
|
+
if (-not (Test-Path $CoreSrcDir)) {
|
|
225
|
+
Write-Host " [FAIL] Missing core directory dist\src\" -ForegroundColor Red
|
|
226
|
+
$PreflightOK = $false
|
|
227
|
+
} else {
|
|
228
|
+
$CoreJsCount = (Get-ChildItem -Path $CoreSrcDir -Filter "*.js" -File -Recurse -ErrorAction SilentlyContinue | Measure-Object).Count
|
|
229
|
+
Write-Host " [OK] dist\src\ contains $CoreJsCount JS files"
|
|
230
|
+
if ($CoreJsCount -lt 5) {
|
|
231
|
+
Write-Host " [FAIL] JS file count too low (expected >= 5, got $CoreJsCount)" -ForegroundColor Red
|
|
232
|
+
$PreflightOK = $false
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# (d) Critical module files
|
|
237
|
+
$MissingModules = @()
|
|
238
|
+
foreach ($mod in @("dist\src\gateway.js", "dist\src\api.js", "dist\src\admin-resolver.js")) {
|
|
239
|
+
if (-not (Test-Path (Join-Path $STAGING_DIR $mod))) {
|
|
240
|
+
$MissingModules += $mod
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if ($MissingModules.Count -gt 0) {
|
|
244
|
+
Write-Host " [FAIL] Missing critical modules: $($MissingModules -join ', ')" -ForegroundColor Red
|
|
245
|
+
$PreflightOK = $false
|
|
246
|
+
} else {
|
|
247
|
+
Write-Host " [OK] Critical modules intact"
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
# (e) Bundled node_modules health check
|
|
251
|
+
$nmDir = Join-Path $STAGING_DIR "node_modules"
|
|
252
|
+
if (Test-Path $nmDir) {
|
|
253
|
+
$BundledOK = $true
|
|
254
|
+
foreach ($dep in @("ws", "silk-wasm")) {
|
|
255
|
+
if (-not (Test-Path (Join-Path $nmDir $dep))) {
|
|
256
|
+
Write-Host " [WARN] Bundled dependency missing: $dep" -ForegroundColor Yellow
|
|
257
|
+
$BundledOK = $false
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if ($BundledOK) {
|
|
261
|
+
Write-Host " [OK] Core bundled dependencies intact"
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
# (f) Version sanity check
|
|
266
|
+
if ($StagingVersion) {
|
|
267
|
+
$StagingMajor = ($StagingVersion -split "\.")[0]
|
|
268
|
+
if ($StagingMajor -eq "0") {
|
|
269
|
+
Write-Host " [WARN] Major version is 0 ($StagingVersion), may not be a production release" -ForegroundColor Yellow
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
# Preflight result
|
|
274
|
+
if (-not $PreflightOK) {
|
|
275
|
+
Write-Host ""
|
|
276
|
+
Write-Host "[ABORT] Preflight checks failed, upgrade cancelled (old version unaffected)" -ForegroundColor Red
|
|
277
|
+
Remove-Item -Recurse -Force $STAGING_DIR -ErrorAction SilentlyContinue
|
|
278
|
+
exit 1
|
|
279
|
+
}
|
|
280
|
+
Write-Host " [OK] All preflight checks passed"
|
|
281
|
+
|
|
282
|
+
# [3/5] Replace plugin directory (in-place overwrite to avoid file-lock issues)
|
|
283
|
+
Write-Host ""
|
|
284
|
+
Write-Host "[3/5] Replacing plugin directory..."
|
|
285
|
+
if (-not (Test-Path $EXTENSIONS_DIR)) { New-Item -ItemType Directory -Path $EXTENSIONS_DIR -Force | Out-Null }
|
|
286
|
+
$TARGET_DIR = Join-Path $EXTENSIONS_DIR "openclaw-qqbot"
|
|
287
|
+
|
|
288
|
+
if (-not (Test-Path $TARGET_DIR)) {
|
|
289
|
+
# Fresh install: just move staging into place
|
|
290
|
+
Move-Item -Path $STAGING_DIR -Destination $TARGET_DIR
|
|
291
|
+
} else {
|
|
292
|
+
# In-place overwrite using robocopy /MIR (mirrors source to dest, works even with locked files)
|
|
293
|
+
Write-Host " Overwriting in-place with robocopy /MIR ..."
|
|
294
|
+
$roboArgs = @($STAGING_DIR, $TARGET_DIR, "/MIR", "/NFL", "/NDL", "/NJH", "/NJS", "/NP", "/R:3", "/W:2")
|
|
295
|
+
$roboResult = & robocopy @roboArgs 2>&1
|
|
296
|
+
$roboExit = $LASTEXITCODE
|
|
297
|
+
# robocopy exit codes: 0-7 = success (various levels of copy), 8+ = error
|
|
298
|
+
if ($roboExit -ge 8) {
|
|
299
|
+
Write-Host " robocopy failed (exit $roboExit), falling back to Copy-Item..." -ForegroundColor Yellow
|
|
300
|
+
# Fallback: recursive Copy-Item -Force (overwrites files even if target exists)
|
|
301
|
+
try {
|
|
302
|
+
Copy-Item -Path (Join-Path $STAGING_DIR "*") -Destination $TARGET_DIR -Recurse -Force -ErrorAction Stop
|
|
303
|
+
Write-Host " Copy-Item fallback succeeded"
|
|
304
|
+
} catch {
|
|
305
|
+
Write-Host " [ERROR] Copy-Item also failed: $($_.Exception.Message)" -ForegroundColor Red
|
|
306
|
+
exit 1
|
|
307
|
+
}
|
|
308
|
+
} else {
|
|
309
|
+
Write-Host " robocopy completed (exit $roboExit)"
|
|
310
|
+
}
|
|
311
|
+
# Clean up staging
|
|
312
|
+
Remove-Item -Recurse -Force $STAGING_DIR -ErrorAction SilentlyContinue
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
# Clean up leftover directories
|
|
316
|
+
foreach ($leftover in @("openclaw-qqbot.staging", ".qqbot-upgrade-staging", ".qqbot-upgrade-old", ".openclaw-qqbot-new")) {
|
|
317
|
+
$p = Join-Path $EXTENSIONS_DIR $leftover
|
|
318
|
+
if (Test-Path $p) { Remove-Item -Recurse -Force $p -ErrorAction SilentlyContinue }
|
|
319
|
+
}
|
|
320
|
+
$oldDir = Join-Path (Split-Path $EXTENSIONS_DIR -Parent) ".qqbot-upgrade-old"
|
|
321
|
+
if (Test-Path $oldDir) { Remove-Item -Recurse -Force $oldDir -ErrorAction SilentlyContinue }
|
|
322
|
+
foreach ($legacyName in @("qqbot", "openclaw-qq")) {
|
|
323
|
+
$p = Join-Path $EXTENSIONS_DIR $legacyName
|
|
324
|
+
if (Test-Path $p) { Remove-Item -Recurse -Force $p -ErrorAction SilentlyContinue }
|
|
325
|
+
}
|
|
326
|
+
Write-Host " Installed to: $TARGET_DIR"
|
|
327
|
+
|
|
328
|
+
# Execute postinstall script to create openclaw SDK symlink
|
|
329
|
+
# (upgrade-via-npm is pure file operation, npm install is not run, so postinstall won't trigger automatically)
|
|
330
|
+
$PostinstallScript = Join-Path $TARGET_DIR "scripts" "postinstall-link-sdk.js"
|
|
331
|
+
if (Test-Path $PostinstallScript) {
|
|
332
|
+
Write-Host " Running postinstall: creating openclaw SDK symlink..."
|
|
333
|
+
try {
|
|
334
|
+
Push-Location $TARGET_DIR
|
|
335
|
+
$postOutput = & node $PostinstallScript 2>&1
|
|
336
|
+
Pop-Location
|
|
337
|
+
if ($postOutput) { Write-Host " $postOutput" }
|
|
338
|
+
} catch {
|
|
339
|
+
Write-Host " [WARN] postinstall script failed (non-fatal)" -ForegroundColor Yellow
|
|
340
|
+
try { Pop-Location } catch {}
|
|
341
|
+
}
|
|
342
|
+
# Verify symlink creation
|
|
343
|
+
$symlinkPath = Join-Path $TARGET_DIR "node_modules" "openclaw"
|
|
344
|
+
if (Test-Path $symlinkPath) {
|
|
345
|
+
Write-Host " [OK] openclaw SDK symlink ready"
|
|
346
|
+
} else {
|
|
347
|
+
Write-Host " [WARN] openclaw SDK symlink not created, attempting manual fallback..." -ForegroundColor Yellow
|
|
348
|
+
$cliDataDir = Split-Path $EXTENSIONS_DIR -Parent
|
|
349
|
+
$cliName = (Split-Path $cliDataDir -Leaf) -replace '^\.',''
|
|
350
|
+
try {
|
|
351
|
+
$globalRoot = (& npm root -g 2>$null).Trim()
|
|
352
|
+
$globalPkg = Join-Path $globalRoot $cliName
|
|
353
|
+
if ($globalRoot -and (Test-Path $globalPkg)) {
|
|
354
|
+
$nmDir = Join-Path $TARGET_DIR "node_modules"
|
|
355
|
+
if (-not (Test-Path $nmDir)) { New-Item -ItemType Directory -Path $nmDir -Force | Out-Null }
|
|
356
|
+
New-Item -ItemType Junction -Path $symlinkPath -Target $globalPkg -Force | Out-Null
|
|
357
|
+
Write-Host " [OK] Manual symlink created: -> $globalPkg"
|
|
358
|
+
} else {
|
|
359
|
+
Write-Host " [ERROR] Cannot locate global $cliName installation (npm root -g: $globalRoot)" -ForegroundColor Red
|
|
360
|
+
}
|
|
361
|
+
} catch {
|
|
362
|
+
Write-Host " [ERROR] Manual symlink creation also failed: $($_.Exception.Message)" -ForegroundColor Red
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
Write-Host " [WARN] postinstall script not found, skipping symlink creation" -ForegroundColor Yellow
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# [4/5] Verify installation
|
|
370
|
+
Write-Host ""
|
|
371
|
+
Write-Host "[4/5] Verifying installation..."
|
|
372
|
+
$NEW_VERSION = "unknown"
|
|
373
|
+
try {
|
|
374
|
+
$newPkgPath = Join-Path $TARGET_DIR "package.json"
|
|
375
|
+
if (Test-Path $newPkgPath) {
|
|
376
|
+
$newPkg = Get-Content $newPkgPath -Raw | ConvertFrom-Json
|
|
377
|
+
if ($newPkg.version) { $NEW_VERSION = $newPkg.version }
|
|
378
|
+
}
|
|
379
|
+
} catch {}
|
|
380
|
+
|
|
381
|
+
Write-Host "QQBOT_NEW_VERSION=$NEW_VERSION"
|
|
382
|
+
|
|
383
|
+
if ($NEW_VERSION -ne "unknown") {
|
|
384
|
+
Write-Host "QQBOT_REPORT=QQBot upgrade complete: v${NEW_VERSION}"
|
|
385
|
+
} else {
|
|
386
|
+
Write-Host "QQBOT_REPORT=[WARN] QQBot upgrade status unknown, cannot confirm new version"
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
Write-Host ""
|
|
390
|
+
Write-Host "==========================================="
|
|
391
|
+
Write-Host " File installation complete"
|
|
392
|
+
Write-Host "==========================================="
|
|
393
|
+
|
|
394
|
+
# --NoRestart mode
|
|
395
|
+
if ($NoRestart) {
|
|
396
|
+
Write-Host ""
|
|
397
|
+
Write-Host "[Skip restart] -NoRestart specified, exiting for caller to trigger gateway restart"
|
|
398
|
+
exit 0
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
# [配置] Configure appid/secret
|
|
402
|
+
if ($AppId -and $Secret) {
|
|
403
|
+
Write-Host ""
|
|
404
|
+
Write-Host "[Config] Writing qqbot channel config..."
|
|
405
|
+
$DESIRED_TOKEN = "${AppId}:${Secret}"
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
& $CMD channels add --channel qqbot --token $DESIRED_TOKEN 2>&1 | Out-Null
|
|
409
|
+
if ($LASTEXITCODE -eq 0) {
|
|
410
|
+
Write-Host " Channel config saved"
|
|
411
|
+
} else { throw "channels add failed" }
|
|
412
|
+
} catch {
|
|
413
|
+
Write-Host " [WARN] $CMD channels add failed, trying direct config edit..." -ForegroundColor Yellow
|
|
414
|
+
$CONFIG_FILE = Join-Path (Join-Path $HOME_DIR ".$CMD") "$CMD.json"
|
|
415
|
+
if (Test-Path $CONFIG_FILE) {
|
|
416
|
+
try {
|
|
417
|
+
$cfg = Get-Content $CONFIG_FILE -Raw | ConvertFrom-Json
|
|
418
|
+
if (-not $cfg.channels) { $cfg | Add-Member -NotePropertyName channels -NotePropertyValue @{} }
|
|
419
|
+
if (-not $cfg.channels.qqbot) { $cfg.channels | Add-Member -NotePropertyName qqbot -NotePropertyValue @{} }
|
|
420
|
+
$cfg.channels.qqbot | Add-Member -NotePropertyName appId -NotePropertyValue $AppId -Force
|
|
421
|
+
$cfg.channels.qqbot | Add-Member -NotePropertyName clientSecret -NotePropertyValue $Secret -Force
|
|
422
|
+
$cfg | ConvertTo-Json -Depth 10 | Set-Content $CONFIG_FILE -Encoding UTF8
|
|
423
|
+
Write-Host " Channel config saved (direct file edit)"
|
|
424
|
+
} catch {
|
|
425
|
+
Write-Host " [ERROR] Config write failed, please configure manually:" -ForegroundColor Red
|
|
426
|
+
Write-Host " $CMD channels add --channel qqbot --token `"${AppId}:${Secret}`""
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} elseif ($AppId -or $Secret) {
|
|
431
|
+
Write-Host ""
|
|
432
|
+
Write-Host "[WARN] -AppId and -Secret must be provided together" -ForegroundColor Yellow
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
# [5/5] Restart gateway
|
|
436
|
+
Write-Host ""
|
|
437
|
+
|
|
438
|
+
# Manual upgrade: write startup-marker before restart to prevent bot from sending duplicate notification
|
|
439
|
+
if ($NEW_VERSION -and $NEW_VERSION -ne "unknown") {
|
|
440
|
+
$MarkerDir = Join-Path $HOME_DIR ".openclaw" "qqbot" "data"
|
|
441
|
+
if (-not (Test-Path $MarkerDir)) { New-Item -ItemType Directory -Path $MarkerDir -Force | Out-Null }
|
|
442
|
+
$MarkerFile = Join-Path $MarkerDir "startup-marker.json"
|
|
443
|
+
$Now = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
|
|
444
|
+
@{ version = $NEW_VERSION; startedAt = $Now; greetedAt = $Now } | ConvertTo-Json -Compress | Set-Content $MarkerFile -Encoding UTF8
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
Write-Host "[Restart] Restarting gateway..."
|
|
448
|
+
try {
|
|
449
|
+
& $CMD gateway restart 2>&1 | Out-Null
|
|
450
|
+
if ($LASTEXITCODE -eq 0) {
|
|
451
|
+
Write-Host " Gateway restarted"
|
|
452
|
+
# Print the same upgrade greeting as bot notification (no need to push via bot in manual upgrade)
|
|
453
|
+
if ($NEW_VERSION -and $NEW_VERSION -ne "unknown") {
|
|
454
|
+
Write-Host ""
|
|
455
|
+
Write-Host "🎉 QQBot 插件已更新至 v${NEW_VERSION},在线等候你的吩咐。"
|
|
456
|
+
}
|
|
457
|
+
} else { throw "restart failed" }
|
|
458
|
+
} catch {
|
|
459
|
+
Write-Host " [WARN] Gateway restart failed, please run manually: $CMD gateway restart" -ForegroundColor Yellow
|
|
460
|
+
}
|