@blockrun/clawrouter 0.12.103 → 0.12.105
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/dist/cli.js +34 -3
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/scripts/reinstall.sh +43 -7
- package/scripts/update.ps1 +223 -0
- package/scripts/update.sh +35 -1
package/package.json
CHANGED
package/scripts/reinstall.sh
CHANGED
|
@@ -323,22 +323,58 @@ if [ -n "$CREDS_BACKUP" ] && [ -d "$CREDS_BACKUP" ]; then
|
|
|
323
323
|
rm -rf "$(dirname "$CREDS_BACKUP")"
|
|
324
324
|
fi
|
|
325
325
|
|
|
326
|
-
# 6.1. Verify installation
|
|
326
|
+
# 6.1. Verify installation and force-update if openclaw installed a stale cached version
|
|
327
327
|
echo "→ Verifying installation..."
|
|
328
328
|
DIST_PATH="$PLUGIN_DIR/dist/index.js"
|
|
329
|
-
if [ ! -f "$DIST_PATH" ]; then
|
|
330
|
-
echo " ⚠️ dist/ files missing, clearing npm cache and retrying..."
|
|
331
|
-
npm cache clean --force 2>/dev/null || true
|
|
332
|
-
rm -rf "$PLUGIN_DIR"
|
|
333
|
-
openclaw plugins install @blockrun/clawrouter
|
|
334
329
|
|
|
330
|
+
force_install_from_npm() {
|
|
331
|
+
local version="$1"
|
|
332
|
+
echo " → Force-fetching v${version} directly from npm registry..."
|
|
333
|
+
local TMPPACK
|
|
334
|
+
TMPPACK=$(mktemp -d)
|
|
335
|
+
if npm pack "@blockrun/clawrouter@${version}" --pack-destination "$TMPPACK" --prefer-online >/dev/null 2>&1; then
|
|
336
|
+
local TARBALL
|
|
337
|
+
TARBALL=$(ls "$TMPPACK"/blockrun-clawrouter-*.tgz 2>/dev/null | head -1)
|
|
338
|
+
if [ -n "$TARBALL" ]; then
|
|
339
|
+
rm -rf "$PLUGIN_DIR"
|
|
340
|
+
mkdir -p "$PLUGIN_DIR"
|
|
341
|
+
tar -xzf "$TARBALL" -C "$PLUGIN_DIR" --strip-components=1
|
|
342
|
+
rm -rf "$TMPPACK"
|
|
343
|
+
echo " ✓ Force-installed v${version} from npm registry"
|
|
344
|
+
return 0
|
|
345
|
+
fi
|
|
346
|
+
fi
|
|
347
|
+
rm -rf "$TMPPACK"
|
|
348
|
+
echo " ✗ Force install failed"
|
|
349
|
+
return 1
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if [ ! -f "$DIST_PATH" ]; then
|
|
353
|
+
echo " ⚠️ dist/ files missing — openclaw install may have cached an old version"
|
|
354
|
+
LATEST_VER=$(npm view @blockrun/clawrouter@latest version 2>/dev/null || echo "")
|
|
355
|
+
if [ -n "$LATEST_VER" ]; then
|
|
356
|
+
force_install_from_npm "$LATEST_VER" || exit 1
|
|
357
|
+
else
|
|
358
|
+
echo " ❌ Cannot determine latest version — check npm registry connection"
|
|
359
|
+
exit 1
|
|
360
|
+
fi
|
|
335
361
|
if [ ! -f "$DIST_PATH" ]; then
|
|
336
362
|
echo " ❌ Installation failed - dist/index.js still missing"
|
|
337
363
|
echo " Please report this issue at https://github.com/BlockRunAI/ClawRouter/issues"
|
|
338
364
|
exit 1
|
|
339
365
|
fi
|
|
366
|
+
else
|
|
367
|
+
# dist/ exists — verify we have the latest version (openclaw may have served cached old version)
|
|
368
|
+
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
369
|
+
LATEST_VER=$(npm view @blockrun/clawrouter@latest version 2>/dev/null || echo "")
|
|
370
|
+
if [ -n "$LATEST_VER" ] && [ -n "$INSTALLED_VER" ] && [ "$INSTALLED_VER" != "$LATEST_VER" ]; then
|
|
371
|
+
echo " ⚠️ openclaw installed v${INSTALLED_VER} (cached) but latest is v${LATEST_VER}"
|
|
372
|
+
force_install_from_npm "$LATEST_VER" || true
|
|
373
|
+
fi
|
|
340
374
|
fi
|
|
341
|
-
|
|
375
|
+
|
|
376
|
+
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('?');}" 2>/dev/null || echo "?")
|
|
377
|
+
echo " ✓ ClawRouter v${INSTALLED_VER} installed"
|
|
342
378
|
|
|
343
379
|
# 6.1b. Ensure all dependencies are installed (Solana, x402, etc.)
|
|
344
380
|
# openclaw's plugin installer may skip native deps like @solana/kit.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# ClawRouter Update Script for Windows (PowerShell)
|
|
2
|
+
# Usage: iwr -useb https://blockrun.ai/ClawRouter-update.ps1 | iex
|
|
3
|
+
# or: powershell -ExecutionPolicy Bypass -Command "iwr -useb https://blockrun.ai/ClawRouter-update.ps1 | iex"
|
|
4
|
+
#
|
|
5
|
+
# Run as regular user (no admin needed)
|
|
6
|
+
Set-StrictMode -Version Latest
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
$PLUGIN_DIR = "$env:USERPROFILE\.openclaw\extensions\clawrouter"
|
|
10
|
+
$CONFIG_PATH = "$env:USERPROFILE\.openclaw\openclaw.json"
|
|
11
|
+
$WALLET_FILE = "$env:USERPROFILE\.openclaw\blockrun\wallet.key"
|
|
12
|
+
|
|
13
|
+
function Write-Ok { param($msg) Write-Host " $([char]0x2713) $msg" -ForegroundColor Green }
|
|
14
|
+
function Write-Warn { param($msg) Write-Host " ! $msg" -ForegroundColor Yellow }
|
|
15
|
+
function Write-Err { param($msg) Write-Host " x $msg" -ForegroundColor Red }
|
|
16
|
+
function Write-Step { param($msg) Write-Host "`n-> $msg" }
|
|
17
|
+
|
|
18
|
+
Write-Host ""
|
|
19
|
+
Write-Host "ClawRouter Update (Windows)" -ForegroundColor Cyan
|
|
20
|
+
Write-Host ""
|
|
21
|
+
|
|
22
|
+
# ── Step 1: Back up wallet ────────────────────────────────────
|
|
23
|
+
Write-Step "Backing up wallet..."
|
|
24
|
+
$walletBackup = $null
|
|
25
|
+
if (Test-Path $WALLET_FILE) {
|
|
26
|
+
$walletKey = (Get-Content $WALLET_FILE -Raw).Trim()
|
|
27
|
+
if ($walletKey -match '^0x[0-9a-fA-F]{64}$') {
|
|
28
|
+
$walletBackup = "$WALLET_FILE.bak.$(Get-Date -UFormat '%s')"
|
|
29
|
+
Copy-Item $WALLET_FILE $walletBackup
|
|
30
|
+
Write-Ok "Wallet backed up: $walletBackup"
|
|
31
|
+
} else {
|
|
32
|
+
Write-Warn "Wallet file found but has unexpected format — skipping backup"
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
Write-Host " i No existing wallet found"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# ── Step 2: Stop old proxy ────────────────────────────────────
|
|
39
|
+
Write-Step "Stopping old proxy..."
|
|
40
|
+
try {
|
|
41
|
+
$procs = Get-NetTCPConnection -LocalPort 8402 -ErrorAction SilentlyContinue |
|
|
42
|
+
Select-Object -ExpandProperty OwningProcess -Unique
|
|
43
|
+
foreach ($pid in $procs) {
|
|
44
|
+
if ($pid -gt 0) { Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue }
|
|
45
|
+
}
|
|
46
|
+
Write-Ok "Port 8402 cleared"
|
|
47
|
+
} catch {
|
|
48
|
+
Write-Host " i Could not check port 8402 (normal if proxy was not running)"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# ── Step 3: Clean stale config entries ────────────────────────
|
|
52
|
+
Write-Step "Cleaning config..."
|
|
53
|
+
if (Test-Path $CONFIG_PATH) {
|
|
54
|
+
try {
|
|
55
|
+
$cfg = Get-Content $CONFIG_PATH -Raw | ConvertFrom-Json
|
|
56
|
+
$changed = $false
|
|
57
|
+
if ($cfg.plugins -and $cfg.plugins.entries -and $cfg.plugins.entries.PSObject.Properties['clawrouter']) {
|
|
58
|
+
$cfg.plugins.entries.PSObject.Properties.Remove('clawrouter')
|
|
59
|
+
$changed = $true
|
|
60
|
+
}
|
|
61
|
+
if ($cfg.plugins -and $cfg.plugins.installs -and $cfg.plugins.installs.PSObject.Properties['clawrouter']) {
|
|
62
|
+
$cfg.plugins.installs.PSObject.Properties.Remove('clawrouter')
|
|
63
|
+
$changed = $true
|
|
64
|
+
}
|
|
65
|
+
if ($changed) {
|
|
66
|
+
$cfg | ConvertTo-Json -Depth 20 | Set-Content $CONFIG_PATH -Encoding UTF8
|
|
67
|
+
Write-Ok "Removed stale plugin entries"
|
|
68
|
+
} else {
|
|
69
|
+
Write-Ok "Config already clean"
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
Write-Warn "Could not parse config: $_"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# ── Step 3b: Ensure baseUrl / apiKey ──────────────────────────
|
|
77
|
+
Write-Step "Verifying provider config..."
|
|
78
|
+
if (Test-Path $CONFIG_PATH) {
|
|
79
|
+
try {
|
|
80
|
+
$cfg = Get-Content $CONFIG_PATH -Raw | ConvertFrom-Json
|
|
81
|
+
$provider = $cfg.models?.providers?.blockrun
|
|
82
|
+
if ($provider) {
|
|
83
|
+
$changed = $false
|
|
84
|
+
if (-not $provider.baseUrl) { $provider | Add-Member -NotePropertyName baseUrl -NotePropertyValue 'http://127.0.0.1:8402/v1' -Force; $changed = $true; Write-Ok "Fixed missing baseUrl" }
|
|
85
|
+
if (-not $provider.apiKey) { $provider | Add-Member -NotePropertyName apiKey -NotePropertyValue 'x402-proxy-handles-auth' -Force; $changed = $true; Write-Ok "Fixed missing apiKey" }
|
|
86
|
+
if ($changed) { $cfg | ConvertTo-Json -Depth 20 | Set-Content $CONFIG_PATH -Encoding UTF8 }
|
|
87
|
+
else { Write-Ok "Provider config OK" }
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
Write-Warn "Could not verify provider config: $_"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# ── Step 4: Get latest version from npm ───────────────────────
|
|
95
|
+
Write-Step "Fetching latest version from npm..."
|
|
96
|
+
try {
|
|
97
|
+
$LATEST_VERSION = (npm view @blockrun/clawrouter@latest version 2>&1).Trim()
|
|
98
|
+
if (-not $LATEST_VERSION -or $LATEST_VERSION -match 'error|ERR') {
|
|
99
|
+
throw "npm view failed: $LATEST_VERSION"
|
|
100
|
+
}
|
|
101
|
+
Write-Ok "Latest: v$LATEST_VERSION"
|
|
102
|
+
} catch {
|
|
103
|
+
Write-Err "Cannot determine latest version: $_"
|
|
104
|
+
Write-Host " Check npm is installed and you have internet access."
|
|
105
|
+
exit 1
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# ── Step 5: Install directly from npm (bypasses openclaw cache) ───
|
|
109
|
+
Write-Step "Downloading ClawRouter v$LATEST_VERSION from npm..."
|
|
110
|
+
|
|
111
|
+
$tmpDir = Join-Path $env:TEMP "clawrouter-install-$(Get-Random)"
|
|
112
|
+
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
npm pack "@blockrun/clawrouter@$LATEST_VERSION" --pack-destination $tmpDir --prefer-online 2>&1 | Out-Null
|
|
116
|
+
|
|
117
|
+
$tarball = Get-ChildItem "$tmpDir\*.tgz" | Select-Object -First 1
|
|
118
|
+
if (-not $tarball) { throw "npm pack produced no tarball in $tmpDir" }
|
|
119
|
+
|
|
120
|
+
# Remove old install
|
|
121
|
+
if (Test-Path $PLUGIN_DIR) {
|
|
122
|
+
Remove-Item -Recurse -Force $PLUGIN_DIR
|
|
123
|
+
}
|
|
124
|
+
New-Item -ItemType Directory -Path $PLUGIN_DIR -Force | Out-Null
|
|
125
|
+
|
|
126
|
+
# Extract (tar is built into Windows 10+ / Server 2019+)
|
|
127
|
+
tar -xzf $tarball.FullName -C $PLUGIN_DIR --strip-components=1
|
|
128
|
+
if ($LASTEXITCODE -ne 0) { throw "tar extraction failed (exit $LASTEXITCODE)" }
|
|
129
|
+
|
|
130
|
+
Write-Ok "Extracted v$LATEST_VERSION to $PLUGIN_DIR"
|
|
131
|
+
} finally {
|
|
132
|
+
Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# ── Step 5b: Install npm dependencies ─────────────────────────
|
|
136
|
+
Write-Step "Installing dependencies (Solana, x402, etc.)..."
|
|
137
|
+
$logFile = Join-Path $env:TEMP "clawrouter-npm-install.log"
|
|
138
|
+
$proc = Start-Process -FilePath "npm" -ArgumentList "install","--omit=dev" -WorkingDirectory $PLUGIN_DIR `
|
|
139
|
+
-RedirectStandardOutput $logFile -RedirectStandardError "$logFile.err" -Wait -PassThru -NoNewWindow
|
|
140
|
+
if ($proc.ExitCode -ne 0) {
|
|
141
|
+
Write-Err "npm install failed. Log: $logFile"
|
|
142
|
+
Get-Content "$logFile.err" -ErrorAction SilentlyContinue | Select-Object -Last 20 | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
|
|
143
|
+
exit 1
|
|
144
|
+
}
|
|
145
|
+
Write-Ok "Dependencies installed"
|
|
146
|
+
|
|
147
|
+
# ── Step 6: Register plugin in openclaw config ────────────────
|
|
148
|
+
Write-Step "Registering plugin..."
|
|
149
|
+
if (Test-Path $CONFIG_PATH) {
|
|
150
|
+
try {
|
|
151
|
+
$cfg = Get-Content $CONFIG_PATH -Raw | ConvertFrom-Json
|
|
152
|
+
if (-not $cfg.plugins) { $cfg | Add-Member -NotePropertyName plugins -NotePropertyValue ([PSCustomObject]@{}) -Force }
|
|
153
|
+
if (-not $cfg.plugins.allow) { $cfg.plugins | Add-Member -NotePropertyName allow -NotePropertyValue @() -Force }
|
|
154
|
+
$allow = [System.Collections.Generic.List[string]]$cfg.plugins.allow
|
|
155
|
+
if (-not $allow.Contains('clawrouter')) {
|
|
156
|
+
$allow.Add('clawrouter')
|
|
157
|
+
$cfg.plugins.allow = $allow.ToArray()
|
|
158
|
+
$cfg | ConvertTo-Json -Depth 20 | Set-Content $CONFIG_PATH -Encoding UTF8
|
|
159
|
+
Write-Ok "Added clawrouter to plugins.allow"
|
|
160
|
+
} else {
|
|
161
|
+
Write-Ok "Plugin already in allow list"
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
Write-Warn "Could not update plugins.allow: $_"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# ── Step 7: Inject auth profile ───────────────────────────────
|
|
169
|
+
Write-Step "Setting up auth profile..."
|
|
170
|
+
$authDir = "$env:USERPROFILE\.openclaw\agents\main\agent"
|
|
171
|
+
$authPath = "$authDir\auth-profiles.json"
|
|
172
|
+
New-Item -ItemType Directory -Path $authDir -Force | Out-Null
|
|
173
|
+
$store = [PSCustomObject]@{ version = 1; profiles = [PSCustomObject]@{} }
|
|
174
|
+
if (Test-Path $authPath) {
|
|
175
|
+
try { $store = Get-Content $authPath -Raw | ConvertFrom-Json } catch {}
|
|
176
|
+
}
|
|
177
|
+
if (-not $store.profiles.PSObject.Properties['blockrun:default']) {
|
|
178
|
+
$store.profiles | Add-Member -NotePropertyName 'blockrun:default' `
|
|
179
|
+
-NotePropertyValue ([PSCustomObject]@{ type = 'api_key'; provider = 'blockrun'; key = 'x402-proxy-handles-auth' }) -Force
|
|
180
|
+
$store | ConvertTo-Json -Depth 10 | Set-Content $authPath -Encoding UTF8
|
|
181
|
+
Write-Ok "Auth profile created"
|
|
182
|
+
} else {
|
|
183
|
+
Write-Ok "Auth profile already exists"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# ── Step 8: Clean models cache ────────────────────────────────
|
|
187
|
+
Write-Step "Cleaning models cache..."
|
|
188
|
+
Get-ChildItem "$env:USERPROFILE\.openclaw\agents\*\agent\models.json" -ErrorAction SilentlyContinue |
|
|
189
|
+
Remove-Item -Force -ErrorAction SilentlyContinue
|
|
190
|
+
Write-Ok "Models cache cleared"
|
|
191
|
+
|
|
192
|
+
# ── Step 9: Verify wallet survived ────────────────────────────
|
|
193
|
+
Write-Step "Verifying wallet integrity..."
|
|
194
|
+
if (Test-Path $WALLET_FILE) {
|
|
195
|
+
$key = (Get-Content $WALLET_FILE -Raw).Trim()
|
|
196
|
+
if ($key -match '^0x[0-9a-fA-F]{64}$') {
|
|
197
|
+
Write-Ok "Wallet key intact"
|
|
198
|
+
} else {
|
|
199
|
+
if ($walletBackup -and (Test-Path $walletBackup)) {
|
|
200
|
+
Copy-Item $walletBackup $WALLET_FILE -Force
|
|
201
|
+
Write-Ok "Wallet restored from backup"
|
|
202
|
+
} else {
|
|
203
|
+
Write-Warn "Wallet file may be corrupted and no backup found"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
if ($walletBackup -and (Test-Path $walletBackup)) {
|
|
208
|
+
New-Item -ItemType Directory -Path (Split-Path $WALLET_FILE) -Force | Out-Null
|
|
209
|
+
Copy-Item $walletBackup $WALLET_FILE -Force
|
|
210
|
+
Write-Ok "Wallet restored from backup"
|
|
211
|
+
} else {
|
|
212
|
+
Write-Host " i No wallet found — a new one will be generated on first start"
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# ── Done ──────────────────────────────────────────────────────
|
|
217
|
+
Write-Host ""
|
|
218
|
+
Write-Host "ClawRouter v$LATEST_VERSION installed successfully!" -ForegroundColor Green
|
|
219
|
+
Write-Host ""
|
|
220
|
+
Write-Host " Run: openclaw gateway restart" -ForegroundColor Cyan
|
|
221
|
+
Write-Host ""
|
|
222
|
+
Write-Host " To verify: npx @blockrun/clawrouter doctor"
|
|
223
|
+
Write-Host ""
|
package/scripts/update.sh
CHANGED
|
@@ -211,7 +211,41 @@ if [ -n "$CREDS_BACKUP" ] && [ -d "$CREDS_BACKUP" ]; then
|
|
|
211
211
|
rm -rf "$(dirname "$CREDS_BACKUP")"
|
|
212
212
|
fi
|
|
213
213
|
|
|
214
|
-
# ── Step 4b:
|
|
214
|
+
# ── Step 4b: Verify version — force-update if openclaw served a stale cache ──
|
|
215
|
+
force_install_from_npm() {
|
|
216
|
+
local version="$1"
|
|
217
|
+
echo " → Force-fetching v${version} directly from npm registry..."
|
|
218
|
+
local TMPPACK
|
|
219
|
+
TMPPACK=$(mktemp -d)
|
|
220
|
+
if npm pack "@blockrun/clawrouter@${version}" --pack-destination "$TMPPACK" --prefer-online >/dev/null 2>&1; then
|
|
221
|
+
local TARBALL
|
|
222
|
+
TARBALL=$(ls "$TMPPACK"/blockrun-clawrouter-*.tgz 2>/dev/null | head -1)
|
|
223
|
+
if [ -n "$TARBALL" ]; then
|
|
224
|
+
rm -rf "$PLUGIN_DIR"
|
|
225
|
+
mkdir -p "$PLUGIN_DIR"
|
|
226
|
+
tar -xzf "$TARBALL" -C "$PLUGIN_DIR" --strip-components=1
|
|
227
|
+
rm -rf "$TMPPACK"
|
|
228
|
+
echo " ✓ Force-installed v${version} from npm registry"
|
|
229
|
+
return 0
|
|
230
|
+
fi
|
|
231
|
+
fi
|
|
232
|
+
rm -rf "$TMPPACK"
|
|
233
|
+
echo " ✗ Force install failed"
|
|
234
|
+
return 1
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if [ -d "$PLUGIN_DIR" ] && [ -f "$PLUGIN_DIR/package.json" ]; then
|
|
238
|
+
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
239
|
+
LATEST_VER=$(npm view @blockrun/clawrouter@latest version 2>/dev/null || echo "")
|
|
240
|
+
if [ -n "$LATEST_VER" ] && [ -n "$INSTALLED_VER" ] && [ "$INSTALLED_VER" != "$LATEST_VER" ]; then
|
|
241
|
+
echo " ⚠️ openclaw installed v${INSTALLED_VER} (cached) but latest is v${LATEST_VER}"
|
|
242
|
+
force_install_from_npm "$LATEST_VER" || true
|
|
243
|
+
fi
|
|
244
|
+
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('?');}" 2>/dev/null || echo "?")
|
|
245
|
+
echo " ✓ ClawRouter v${INSTALLED_VER} installed"
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
# ── Step 4c: Ensure all dependencies are installed ────────────
|
|
215
249
|
# openclaw's plugin installer may skip native/optional deps like @solana/kit.
|
|
216
250
|
# Run npm install in the plugin directory to fill any gaps.
|
|
217
251
|
if [ -d "$PLUGIN_DIR" ] && [ -f "$PLUGIN_DIR/package.json" ]; then
|