@ckcloudai.com/clawrouter 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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +6596 -0
- package/dist/index.js.map +1 -0
- package/openclaw.plugin.json +25 -0
- package/package.json +68 -0
- package/scripts/reinstall.sh +343 -0
- package/scripts/uninstall.sh +157 -0
- package/scripts/update.sh +382 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "🦞 ckcloud\n"
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
echo "🦞 ckcloud plugin reinstall"
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
14
|
+
echo "jq is required"
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
############### 0. Back up wallet key BEFORE removing anything ###############
|
|
19
|
+
WALLET_FILE="$HOME/.openclaw/ckcloud/wallet.key"
|
|
20
|
+
WALLET_BACKUP=""
|
|
21
|
+
|
|
22
|
+
if [ -f "$WALLET_FILE" ]; then
|
|
23
|
+
echo "→ Backing up wallet..."
|
|
24
|
+
WALLET_KEY=$(cat "$WALLET_FILE" | tr -d '[:space:]')
|
|
25
|
+
KEY_LEN=${#WALLET_KEY}
|
|
26
|
+
if [[ "$WALLET_KEY" == 0x* ]] && [ "$KEY_LEN" -eq 66 ]; then
|
|
27
|
+
WALLET_BACKUP="$HOME/.openclaw/ckcloud/wallet.key.bak.$(date +%s)"
|
|
28
|
+
cp "$WALLET_FILE" "$WALLET_BACKUP"
|
|
29
|
+
chmod 600 "$WALLET_BACKUP"
|
|
30
|
+
echo " ✓ Wallet backed up to: $WALLET_BACKUP"
|
|
31
|
+
else
|
|
32
|
+
echo " ⚠ Wallet file exists but has invalid format — skipping backup"
|
|
33
|
+
fi
|
|
34
|
+
else
|
|
35
|
+
if [ -f "$HOME/.openclaw/ckcloud/mnemonic" ]; then
|
|
36
|
+
echo " ⚠ wallet.key missing but mnemonic exists — refusing to overwrite funds"
|
|
37
|
+
echo " Run: npx @ckcloudai.com/clawrouter wallet recover"
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
echo "→ No wallet found — generating a new wallet (fresh install)"
|
|
41
|
+
fi
|
|
42
|
+
echo ""
|
|
43
|
+
|
|
44
|
+
############### 1. Remove plugin files ###############
|
|
45
|
+
echo "→ Removing plugin files..."
|
|
46
|
+
rm -rf ~/.openclaw/extensions/ckcloud
|
|
47
|
+
|
|
48
|
+
############### 2. clean config ###############
|
|
49
|
+
CONFIG="$HOME/.openclaw/openclaw.json"
|
|
50
|
+
|
|
51
|
+
## check file exist
|
|
52
|
+
if [ ! -f "$CONFIG" ]; then
|
|
53
|
+
echo " No openclaw.json found, skipping"
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
## check json
|
|
58
|
+
if ! jq empty "$CONFIG" >/dev/null 2>&1; then
|
|
59
|
+
backup="$CONFIG.corrupt.$(date +%s)"
|
|
60
|
+
echo " ERROR: Invalid JSON in openclaw.json"
|
|
61
|
+
cp "$CONFIG" "$backup" || true
|
|
62
|
+
echo " Backed up to: $backup"
|
|
63
|
+
echo " Skipping config cleanup..."
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
tmp=$(mktemp)
|
|
68
|
+
|
|
69
|
+
## clean config
|
|
70
|
+
jq '
|
|
71
|
+
if .plugins.entries.ckcloud then
|
|
72
|
+
del(.plugins.entries.ckcloud)
|
|
73
|
+
else . end |
|
|
74
|
+
|
|
75
|
+
if .plugins.installs.ckcloud then
|
|
76
|
+
del(.plugins.installs.ckcloud)
|
|
77
|
+
else . end |
|
|
78
|
+
|
|
79
|
+
if .plugins.allow then
|
|
80
|
+
.plugins.allow |= map(select(. != "ckcloud" and . != "@ckcloudai.com/clawrouter"))
|
|
81
|
+
else . end
|
|
82
|
+
|
|
83
|
+
' "$CONFIG" > "$tmp"
|
|
84
|
+
|
|
85
|
+
mv "$tmp" "$CONFIG"
|
|
86
|
+
|
|
87
|
+
echo " Config cleaned"
|
|
88
|
+
|
|
89
|
+
############### 3. stop old plugin proxy ###############
|
|
90
|
+
PORT_TO_KILL=8402
|
|
91
|
+
|
|
92
|
+
stop_proxy() {
|
|
93
|
+
local port="$1"
|
|
94
|
+
local os_name pids=
|
|
95
|
+
os_name=$(uname -s 2>/dev/null || echo "")
|
|
96
|
+
|
|
97
|
+
if command -v lsof >/dev/null 2>&1; then
|
|
98
|
+
pids=$(lsof -ti tcp:"$port" 2>/dev/null | tr '\n' ' ')
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
if [ -z "$pids" ] && [[ "$os_name" == Linux* ]] && command -v fuser >/dev/null 2>&1; then
|
|
102
|
+
pids=$(fuser -n tcp "$port" 2>/dev/null | tr '\n' ' ')
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
if [ -z "$pids" ]; then
|
|
106
|
+
echo "→ No proxy process detected on port $port"
|
|
107
|
+
return
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
for pid in $pids; do
|
|
111
|
+
if [ -z "$pid" ]; then
|
|
112
|
+
continue
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if kill "$pid" >/dev/null 2>&1; then
|
|
116
|
+
echo "→ Stopped process $pid"
|
|
117
|
+
else
|
|
118
|
+
echo "→ Failed to stop process $pid"
|
|
119
|
+
fi
|
|
120
|
+
done
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
case "$(uname -s 2>/dev/null || echo "")" in
|
|
124
|
+
Darwin*|Linux*)
|
|
125
|
+
echo "→ Stopping proxy on port $PORT_TO_KILL..."
|
|
126
|
+
stop_proxy "$PORT_TO_KILL"
|
|
127
|
+
;;
|
|
128
|
+
*)
|
|
129
|
+
echo "→ Unsupported platform, skipping proxy stop"
|
|
130
|
+
;;
|
|
131
|
+
esac
|
|
132
|
+
|
|
133
|
+
############### 4. Remove stale models.json so it gets regenerated with apiKey ###############
|
|
134
|
+
echo "→ Cleaning models cache..."
|
|
135
|
+
rm -f ~/.openclaw/agents/main/agent/models.json 2>/dev/null || true
|
|
136
|
+
|
|
137
|
+
############### 5. Inject auth profile ###############
|
|
138
|
+
echo "→ Injecting auth profile..."
|
|
139
|
+
|
|
140
|
+
AUTH_DIR="$HOME/.openclaw/agents/main/agent"
|
|
141
|
+
AUTH_PATH="$AUTH_DIR/auth-profiles.json"
|
|
142
|
+
PROFILE_KEY="ckcloud:default"
|
|
143
|
+
|
|
144
|
+
mkdir -p "$AUTH_DIR"
|
|
145
|
+
|
|
146
|
+
reset_auth_store() {
|
|
147
|
+
cat <<'EOF' > "$AUTH_PATH"
|
|
148
|
+
{
|
|
149
|
+
"version": 1,
|
|
150
|
+
"profiles": {}
|
|
151
|
+
}
|
|
152
|
+
EOF
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if [ -f "$AUTH_PATH" ]; then
|
|
156
|
+
if jq empty "$AUTH_PATH" >/dev/null 2>&1; then
|
|
157
|
+
if ! jq -e '.version and .profiles' "$AUTH_PATH" >/dev/null 2>&1; then
|
|
158
|
+
echo " Warning: auth-profiles.json missing version/profiles, recreating"
|
|
159
|
+
reset_auth_store
|
|
160
|
+
fi
|
|
161
|
+
else
|
|
162
|
+
echo " Warning: Could not parse auth-profiles.json, creating fresh"
|
|
163
|
+
reset_auth_store
|
|
164
|
+
fi
|
|
165
|
+
else
|
|
166
|
+
reset_auth_store
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
tmp_auth=$(mktemp)
|
|
170
|
+
if jq --arg key "$PROFILE_KEY" \
|
|
171
|
+
--arg type "api_key" \
|
|
172
|
+
--arg provider "ckcloud" \
|
|
173
|
+
--arg api_key "x402-proxy-handles-auth" \
|
|
174
|
+
'if .profiles[$key] then . else .profiles[$key] = {type: $type, provider: $provider, key: $api_key} end' \
|
|
175
|
+
"$AUTH_PATH" > "$tmp_auth"; then
|
|
176
|
+
if cmp -s "$AUTH_PATH" "$tmp_auth"; then
|
|
177
|
+
echo " Auth profile already exists"
|
|
178
|
+
rm -f "$tmp_auth"
|
|
179
|
+
else
|
|
180
|
+
mv "$tmp_auth" "$AUTH_PATH"
|
|
181
|
+
echo " Auth profile created"
|
|
182
|
+
fi
|
|
183
|
+
else
|
|
184
|
+
echo " ERROR: Failed to update auth profile"
|
|
185
|
+
rm -f "$tmp_auth"
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
############### 6. Ensure apiKey is present for /model picker (but DON'T override default model) ###############
|
|
189
|
+
#!/usr/bin/env bash
|
|
190
|
+
if [ ! -f "$CONFIG" ]; then
|
|
191
|
+
echo " No openclaw.json found, skipping"
|
|
192
|
+
exit 0
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
APIKEY=$(jq -r '.models.providers.ckcloud.apiKey // empty' "$CONFIG")
|
|
196
|
+
|
|
197
|
+
if [ -z "$APIKEY" ]; then
|
|
198
|
+
echo " Added apiKey to ckcloud provider config"
|
|
199
|
+
|
|
200
|
+
tmp=$(mktemp)
|
|
201
|
+
|
|
202
|
+
jq '.models.providers.ckcloud.apiKey = "x402-proxy-handles-auth"' \
|
|
203
|
+
"$CONFIG" > "$tmp" && mv "$tmp" "$CONFIG"
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
############### 7. Populate model allowlist so top ckcloud models appear in /model picker ###############
|
|
208
|
+
TMP=$(mktemp)
|
|
209
|
+
|
|
210
|
+
TOP_MODELS=(
|
|
211
|
+
auto free eco premium
|
|
212
|
+
anthropic/claude-sonnet-4.6
|
|
213
|
+
)
|
|
214
|
+
TOP_JSON=$(printf '"ckcloud/%s",' "${TOP_MODELS[@]}")
|
|
215
|
+
TOP_JSON="[${TOP_JSON%,}]"
|
|
216
|
+
|
|
217
|
+
# 确保 provider + apiKey
|
|
218
|
+
jq '
|
|
219
|
+
.models |= (. // {}) |
|
|
220
|
+
.models.providers |= (. // {}) |
|
|
221
|
+
.models.providers.ckcloud |= (. // {api:"openai-completions",models:[],baseUrl:"http://127.0.0.1:8402/v1"}) |
|
|
222
|
+
.models.providers.ckcloud.baseUrl |= (. // "http://127.0.0.1:8402/v1") |
|
|
223
|
+
.models.providers.ckcloud.apiKey |= (. // "x402-proxy-handles-auth") |
|
|
224
|
+
.models.providers.ckcloud.models |= (. // [])
|
|
225
|
+
' "$CONFIG" > "$TMP"
|
|
226
|
+
|
|
227
|
+
mv "$TMP" "$CONFIG"
|
|
228
|
+
|
|
229
|
+
# 清理旧 ckcloud/*
|
|
230
|
+
TMP=$(mktemp)
|
|
231
|
+
|
|
232
|
+
jq --argjson top "$TOP_JSON" '
|
|
233
|
+
.agents |= (. // {}) |
|
|
234
|
+
.agents.defaults |= (. // {}) |
|
|
235
|
+
.agents.defaults.models |= (. // {}) |
|
|
236
|
+
.agents.defaults.models |= with_entries(
|
|
237
|
+
if (.key | startswith("ckcloud/")) and
|
|
238
|
+
(.key as $k | ($top | index($k)) | not)
|
|
239
|
+
then empty
|
|
240
|
+
else .
|
|
241
|
+
end
|
|
242
|
+
)
|
|
243
|
+
' "$CONFIG" > "$TMP"
|
|
244
|
+
|
|
245
|
+
mv "$TMP" "$CONFIG"
|
|
246
|
+
|
|
247
|
+
# 添加 TOP_MODELS
|
|
248
|
+
added=0
|
|
249
|
+
|
|
250
|
+
for id in "${TOP_MODELS[@]}"; do
|
|
251
|
+
key="ckcloud/$id"
|
|
252
|
+
|
|
253
|
+
if ! jq -e --arg k "$key" '.agents.defaults.models[$k]' "$CONFIG" >/dev/null; then
|
|
254
|
+
TMP=$(mktemp)
|
|
255
|
+
|
|
256
|
+
jq --arg k "$key" '
|
|
257
|
+
.agents.defaults.models[$k] = {}
|
|
258
|
+
' "$CONFIG" > "$TMP"
|
|
259
|
+
|
|
260
|
+
mv "$TMP" "$CONFIG"
|
|
261
|
+
added=$((added+1))
|
|
262
|
+
fi
|
|
263
|
+
done
|
|
264
|
+
|
|
265
|
+
if [ "$added" -gt 0 ]; then
|
|
266
|
+
echo " Added $added models to allowlist (${#TOP_MODELS[@]} total)"
|
|
267
|
+
else
|
|
268
|
+
echo " Allowlist already up to date"
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
############### 8. Ensure default primary model uses ckcloud/auto ###############
|
|
272
|
+
echo "→ Ensuring default primary model..."
|
|
273
|
+
|
|
274
|
+
current_model=$(jq -r '.agents.defaults.model.primary // empty' "$CONFIG")
|
|
275
|
+
|
|
276
|
+
if [ "$current_model" = "ckcloud/auto" ]; then
|
|
277
|
+
echo " Default primary already ckcloud/auto"
|
|
278
|
+
else
|
|
279
|
+
TMP=$(mktemp)
|
|
280
|
+
|
|
281
|
+
if jq '
|
|
282
|
+
.agents |= (. // {}) |
|
|
283
|
+
.agents.defaults |= (. // {}) |
|
|
284
|
+
.agents.defaults.model |= (. // {}) |
|
|
285
|
+
.agents.defaults.model.primary = "ckcloud/auto"
|
|
286
|
+
' "$CONFIG" > "$TMP"; then
|
|
287
|
+
mv "$TMP" "$CONFIG"
|
|
288
|
+
if [ -z "$current_model" ]; then
|
|
289
|
+
echo " Set primary to ckcloud/auto"
|
|
290
|
+
else
|
|
291
|
+
echo " Replaced primary ($current_model) → ckcloud/auto"
|
|
292
|
+
fi
|
|
293
|
+
else
|
|
294
|
+
echo " Failed to update default model"
|
|
295
|
+
rm -f "$TMP"
|
|
296
|
+
fi
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
############### 9. Install plugin (config is ready, but no allow list yet to avoid validation error) ###############
|
|
300
|
+
echo "→ Installing ckcloud plugin..."
|
|
301
|
+
|
|
302
|
+
openclaw plugins install @ckcloudai.com/clawrouter
|
|
303
|
+
|
|
304
|
+
echo "→ Verifying installation..."
|
|
305
|
+
DIST_PATH="$HOME/.openclaw/extensions/ckcloud/dist/index.js"
|
|
306
|
+
if [ ! -f "$DIST_PATH" ]; then
|
|
307
|
+
echo " ⚠️ dist/ files missing, clearing npm cache and retrying..."
|
|
308
|
+
npm cache clean --force 2>/dev/null || true
|
|
309
|
+
rm -rf ~/.openclaw/extensions/ckcloud
|
|
310
|
+
|
|
311
|
+
openclaw plugins install @ckcloudai.com/clawrouter
|
|
312
|
+
|
|
313
|
+
if [ ! -f "$DIST_PATH" ]; then
|
|
314
|
+
echo " ❌ Installation failed - dist/index.js still missing"
|
|
315
|
+
echo " Please report this issue"
|
|
316
|
+
exit 1
|
|
317
|
+
fi
|
|
318
|
+
fi
|
|
319
|
+
echo " ✓ dist/index.js verified"
|
|
320
|
+
|
|
321
|
+
############### 10. Add plugin to allow list (done AFTER install so plugin files exist for validation) ###############
|
|
322
|
+
TMP_FILE=$(mktemp)
|
|
323
|
+
|
|
324
|
+
if jq '
|
|
325
|
+
.plugins = (.plugins // {}) |
|
|
326
|
+
.plugins.allow = (.plugins.allow // []) |
|
|
327
|
+
if (.plugins.allow | index("ckcloud")) or (.plugins.allow | index("@ckcloudai.com/clawrouter")) then
|
|
328
|
+
.
|
|
329
|
+
else
|
|
330
|
+
.plugins.allow += ["ckcloud"]
|
|
331
|
+
end
|
|
332
|
+
' "$CONFIG" > "$TMP_FILE"; then
|
|
333
|
+
|
|
334
|
+
if jq -e '.plugins.allow | index("ckcloud")' "$CONFIG" >/dev/null 2>&1 || \
|
|
335
|
+
jq -e '.plugins.allow | index("@ckcloudai.com/clawrouter")' "$CONFIG" >/dev/null 2>&1; then
|
|
336
|
+
echo " Plugin already in allow list"
|
|
337
|
+
else
|
|
338
|
+
echo " Added ckcloud to plugins.allow"
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
mv "$TMP_FILE" "$CONFIG"
|
|
342
|
+
else
|
|
343
|
+
echo " Could not update config"
|
|
344
|
+
rm -f "$TMP_FILE"
|
|
345
|
+
fi
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
############### Final: verify wallet survived reinstall ###############
|
|
349
|
+
echo "→ Verifying wallet integrity..."
|
|
350
|
+
if [ -f "$WALLET_FILE" ]; then
|
|
351
|
+
CURRENT_KEY=$(cat "$WALLET_FILE" | tr -d '[:space:]')
|
|
352
|
+
CURRENT_LEN=${#CURRENT_KEY}
|
|
353
|
+
if [[ "$CURRENT_KEY" == 0x* ]] && [ "$CURRENT_LEN" -eq 66 ]; then
|
|
354
|
+
echo " ✓ Wallet key intact"
|
|
355
|
+
else
|
|
356
|
+
if [ -n "$WALLET_BACKUP" ] && [ -f "$WALLET_BACKUP" ]; then
|
|
357
|
+
cp "$WALLET_BACKUP" "$WALLET_FILE"
|
|
358
|
+
chmod 600 "$WALLET_FILE"
|
|
359
|
+
echo " ✓ Wallet restored from backup"
|
|
360
|
+
else
|
|
361
|
+
echo " ⚠ wallet.key corrupted AND no backup available. Manual recovery required."
|
|
362
|
+
echo " Run: npx @ckcloudai.com/clawrouter wallet recover"
|
|
363
|
+
fi
|
|
364
|
+
fi
|
|
365
|
+
else
|
|
366
|
+
if [ -n "$WALLET_BACKUP" ] && [ -f "$WALLET_BACKUP" ]; then
|
|
367
|
+
mkdir -p "$(dirname "$WALLET_FILE")"
|
|
368
|
+
cp "$WALLET_BACKUP" "$WALLET_FILE"
|
|
369
|
+
chmod 600 "$WALLET_FILE"
|
|
370
|
+
echo " ✓ Wallet restored from backup: $WALLET_BACKUP"
|
|
371
|
+
else
|
|
372
|
+
echo " ⚠ wallet.key missing and no backup available. Manual recovery required."
|
|
373
|
+
echo " Run: npx @ckcloudai.com/clawrouter wallet recover"
|
|
374
|
+
fi
|
|
375
|
+
fi
|
|
376
|
+
|
|
377
|
+
echo ""
|
|
378
|
+
echo "✓ Done! Smart routing enabled by default."
|
|
379
|
+
echo ""
|
|
380
|
+
echo "Run: openclaw gateway restart"
|
|
381
|
+
|
|
382
|
+
echo "To uninstall: bash ~/.openclaw/extensions/ckcloud/scripts/uninstall.sh"
|