nightpay 0.3.2 → 0.3.11
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.
Potentially problematic release.
This version of nightpay might be problematic. Click here for more details.
- package/README.md +136 -10
- package/bin/cli.js +43 -5
- package/bin/deploy-hetzner-ci.sh +428 -0
- package/openclaw.plugin.json +10 -0
- package/package.json +15 -5
- package/plugin.js +379 -0
- package/scripts/agent-playground-setup.sh +33 -10
- package/scripts/load-sim.sh +641 -17
- package/scripts/server-sync-start.sh +82 -6
- package/skills/nightpay/AGENTS.md +20 -1
- package/skills/nightpay/SKILL.md +34 -27
- package/skills/nightpay/openclaw-fragment.json +21 -1
- package/skills/nightpay/scripts/gateway.sh +132 -23
- package/skills/nightpay/scripts/mip003-server.sh +1157 -125
- package/scripts/setup.sh +0 -489
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'EOF'
|
|
6
|
+
Usage:
|
|
7
|
+
bash bin/deploy-hetzner-ci.sh \
|
|
8
|
+
--host <hostname-or-ip> \
|
|
9
|
+
--ssh-key <path-to-private-key> \
|
|
10
|
+
[--ssh-port 22] \
|
|
11
|
+
[--remote-dir /opt/nightpay] \
|
|
12
|
+
[--bridge-dir /opt/nightpay-bridge] \
|
|
13
|
+
[--masumi-dir /opt/masumi-services-dev-quickstart] \
|
|
14
|
+
[--ui-port 3333] \
|
|
15
|
+
[--mip-port 8090] \
|
|
16
|
+
[--skip-npm-install] \
|
|
17
|
+
[--skip-proof-recreate] \
|
|
18
|
+
[--skip-masumi-recreate]
|
|
19
|
+
|
|
20
|
+
This script is intended for CI/CD usage.
|
|
21
|
+
It syncs the current committed HEAD to the server, restarts NightPay services,
|
|
22
|
+
recreates Docker services, and fails fast on health-check failures.
|
|
23
|
+
EOF
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
HOST=""
|
|
27
|
+
SSH_KEY=""
|
|
28
|
+
SSH_PORT="22"
|
|
29
|
+
REMOTE_DIR="/opt/nightpay"
|
|
30
|
+
BRIDGE_DIR="/opt/nightpay-bridge"
|
|
31
|
+
MASUMI_DIR="/opt/masumi-services-dev-quickstart"
|
|
32
|
+
SKIP_NPM_INSTALL=0
|
|
33
|
+
SKIP_PROOF_RECREATE=0
|
|
34
|
+
SKIP_MASUMI_RECREATE=0
|
|
35
|
+
UI_PORT=""
|
|
36
|
+
MIP_PORT=""
|
|
37
|
+
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--host)
|
|
41
|
+
HOST="${2:-}"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
--ssh-key)
|
|
45
|
+
SSH_KEY="${2:-}"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
--ssh-port)
|
|
49
|
+
SSH_PORT="${2:-}"
|
|
50
|
+
shift 2
|
|
51
|
+
;;
|
|
52
|
+
--remote-dir)
|
|
53
|
+
REMOTE_DIR="${2:-}"
|
|
54
|
+
shift 2
|
|
55
|
+
;;
|
|
56
|
+
--bridge-dir)
|
|
57
|
+
BRIDGE_DIR="${2:-}"
|
|
58
|
+
shift 2
|
|
59
|
+
;;
|
|
60
|
+
--masumi-dir)
|
|
61
|
+
MASUMI_DIR="${2:-}"
|
|
62
|
+
shift 2
|
|
63
|
+
;;
|
|
64
|
+
--skip-npm-install)
|
|
65
|
+
SKIP_NPM_INSTALL=1
|
|
66
|
+
shift
|
|
67
|
+
;;
|
|
68
|
+
--skip-proof-recreate)
|
|
69
|
+
SKIP_PROOF_RECREATE=1
|
|
70
|
+
shift
|
|
71
|
+
;;
|
|
72
|
+
--skip-masumi-recreate)
|
|
73
|
+
SKIP_MASUMI_RECREATE=1
|
|
74
|
+
shift
|
|
75
|
+
;;
|
|
76
|
+
--ui-port)
|
|
77
|
+
UI_PORT="${2:-}"
|
|
78
|
+
shift 2
|
|
79
|
+
;;
|
|
80
|
+
--mip-port)
|
|
81
|
+
MIP_PORT="${2:-}"
|
|
82
|
+
shift 2
|
|
83
|
+
;;
|
|
84
|
+
-h|--help)
|
|
85
|
+
usage
|
|
86
|
+
exit 0
|
|
87
|
+
;;
|
|
88
|
+
*)
|
|
89
|
+
echo "ERROR: unknown arg '$1'" >&2
|
|
90
|
+
usage
|
|
91
|
+
exit 1
|
|
92
|
+
;;
|
|
93
|
+
esac
|
|
94
|
+
done
|
|
95
|
+
|
|
96
|
+
if [[ -z "$HOST" || -z "$SSH_KEY" ]]; then
|
|
97
|
+
usage
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
if [[ ! -f "$SSH_KEY" ]]; then
|
|
102
|
+
echo "ERROR: SSH key not found: $SSH_KEY" >&2
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
107
|
+
SSH_OPTS=(
|
|
108
|
+
-i "$SSH_KEY"
|
|
109
|
+
-p "$SSH_PORT"
|
|
110
|
+
-o BatchMode=yes
|
|
111
|
+
-o StrictHostKeyChecking=accept-new
|
|
112
|
+
-o ConnectTimeout=20
|
|
113
|
+
-o ServerAliveInterval=15
|
|
114
|
+
-o ServerAliveCountMax=4
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
run_ssh() {
|
|
118
|
+
local remote_cmd="$1"
|
|
119
|
+
ssh "${SSH_OPTS[@]}" "root@${HOST}" "$remote_cmd"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
echo "[1/9] Verify SSH connectivity..."
|
|
123
|
+
run_ssh "echo connected: \$(hostname)"
|
|
124
|
+
|
|
125
|
+
echo "[2/9] Verify server architecture..."
|
|
126
|
+
ARCH="$(run_ssh "uname -m")"
|
|
127
|
+
if [[ "$ARCH" != "x86_64" ]]; then
|
|
128
|
+
echo "ERROR: expected x86_64 server for Masumi compatibility; found: $ARCH" >&2
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
echo "[3/9] Backup remote env files..."
|
|
133
|
+
run_ssh "\
|
|
134
|
+
set -euo pipefail; \
|
|
135
|
+
mkdir -p '${REMOTE_DIR}/.backups'; \
|
|
136
|
+
ts=\$(date +%Y%m%d-%H%M%S); \
|
|
137
|
+
for f in '${REMOTE_DIR}/.agent-playground.env' '${REMOTE_DIR}/.env' '${BRIDGE_DIR}/.env' '${MASUMI_DIR}/.env'; do \
|
|
138
|
+
if [[ -f \"\$f\" ]]; then cp \"\$f\" '${REMOTE_DIR}/.backups/'\"\$(basename \"\$f\")\"'.'\"\$ts\"; fi; \
|
|
139
|
+
done; \
|
|
140
|
+
echo backup_timestamp=\$ts"
|
|
141
|
+
|
|
142
|
+
echo "[4/9] Stop NightPay services before sync..."
|
|
143
|
+
run_ssh "\
|
|
144
|
+
set -euo pipefail; \
|
|
145
|
+
if [[ ! -d '${REMOTE_DIR}' ]]; then exit 0; fi; \
|
|
146
|
+
if id -u deploy >/dev/null 2>&1; then \
|
|
147
|
+
if [[ -f '${REMOTE_DIR}/scripts/agent-playground-setup.sh' ]]; then \
|
|
148
|
+
su - deploy -c \"cd '${REMOTE_DIR}' && bash scripts/agent-playground-setup.sh stop || true\"; \
|
|
149
|
+
fi; \
|
|
150
|
+
pkill -u deploy -f '${REMOTE_DIR}/skills/nightpay/scripts/mip003-server.sh' || true; \
|
|
151
|
+
pkill -u deploy -f '${REMOTE_DIR}/ui/node_modules/.bin/vite' || true; \
|
|
152
|
+
fi; \
|
|
153
|
+
rm -f '${REMOTE_DIR}/.agent-playground/run/'*.pid || true; \
|
|
154
|
+
rm -rf '${REMOTE_DIR}/ui/.vite' '${REMOTE_DIR}/ui/node_modules/.vite' || true"
|
|
155
|
+
|
|
156
|
+
echo "[5/9] Sync tracked commit to ${HOST}:${REMOTE_DIR}..."
|
|
157
|
+
TMP_SYNC_DIR="$(mktemp -d)"
|
|
158
|
+
cleanup_tmp() { rm -rf "$TMP_SYNC_DIR"; }
|
|
159
|
+
trap cleanup_tmp EXIT
|
|
160
|
+
|
|
161
|
+
git -C "$ROOT_DIR" archive --format=tar HEAD | tar -xf - -C "$TMP_SYNC_DIR"
|
|
162
|
+
|
|
163
|
+
# If ui/ exists locally (for example checked-out private submodule), include it in deploy payload.
|
|
164
|
+
if [[ -f "$ROOT_DIR/ui/package.json" ]]; then
|
|
165
|
+
mkdir -p "$TMP_SYNC_DIR/ui"
|
|
166
|
+
tar -C "$ROOT_DIR/ui" \
|
|
167
|
+
--exclude=.git \
|
|
168
|
+
--exclude=node_modules \
|
|
169
|
+
--exclude=dist \
|
|
170
|
+
-cf - . | tar -xf - -C "$TMP_SYNC_DIR/ui"
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
tar -C "$TMP_SYNC_DIR" -cf - . \
|
|
174
|
+
| ssh "${SSH_OPTS[@]}" "root@${HOST}" "\
|
|
175
|
+
set -euo pipefail; \
|
|
176
|
+
mkdir -p '${REMOTE_DIR}'; \
|
|
177
|
+
find '${REMOTE_DIR}' -mindepth 1 -maxdepth 1 \
|
|
178
|
+
! -name '.backups' \
|
|
179
|
+
! -name '.agent-playground' \
|
|
180
|
+
! -name '.agent-playground.env' \
|
|
181
|
+
! -name '.env' \
|
|
182
|
+
-exec rm -rf {} +; \
|
|
183
|
+
tar -xf - -C '${REMOTE_DIR}'; \
|
|
184
|
+
if ! id -u deploy >/dev/null 2>&1; then useradd -m -s /bin/bash -G sudo,docker deploy; fi; \
|
|
185
|
+
chown -R deploy:deploy '${REMOTE_DIR}'; \
|
|
186
|
+
find '${REMOTE_DIR}' -type f -name '*.sh' -exec sed -i 's/\r$//' {} +"
|
|
187
|
+
|
|
188
|
+
cleanup_tmp
|
|
189
|
+
trap - EXIT
|
|
190
|
+
|
|
191
|
+
echo "[6/9] Restart NightPay services..."
|
|
192
|
+
ssh "${SSH_OPTS[@]}" "root@${HOST}" \
|
|
193
|
+
"REMOTE_DIR='${REMOTE_DIR}' SKIP_NPM_INSTALL='${SKIP_NPM_INSTALL}' UI_PORT='${UI_PORT}' MIP_PORT='${MIP_PORT}' SKIP_MASUMI_RECREATE='${SKIP_MASUMI_RECREATE}' bash -s" <<'REMOTE'
|
|
194
|
+
set -euo pipefail
|
|
195
|
+
|
|
196
|
+
if [[ "$SKIP_NPM_INSTALL" != "1" ]]; then
|
|
197
|
+
su - deploy -c "cd '$REMOTE_DIR' && npm install --no-audit --no-fund"
|
|
198
|
+
if [[ -f "$REMOTE_DIR/ui/package.json" ]]; then
|
|
199
|
+
su - deploy -c "cd '$REMOTE_DIR/ui' && npm install --no-audit --no-fund"
|
|
200
|
+
else
|
|
201
|
+
echo "WARN: $REMOTE_DIR/ui/package.json missing; skipping UI npm install."
|
|
202
|
+
fi
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
if [[ ! -f "$REMOTE_DIR/.agent-playground.env" ]]; then
|
|
206
|
+
if [[ "$SKIP_MASUMI_RECREATE" == "1" && "$REMOTE_DIR" != "/opt/nightpay" && -f "/opt/nightpay/.agent-playground.env" ]]; then
|
|
207
|
+
cp /opt/nightpay/.agent-playground.env "$REMOTE_DIR/.agent-playground.env"
|
|
208
|
+
chown deploy:deploy "$REMOTE_DIR/.agent-playground.env" || true
|
|
209
|
+
else
|
|
210
|
+
su - deploy -c "cd '$REMOTE_DIR' && bash scripts/agent-playground-setup.sh init"
|
|
211
|
+
fi
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
if [[ "$SKIP_MASUMI_RECREATE" == "1" && -f "/opt/nightpay/.agent-playground.env" ]]; then
|
|
215
|
+
python3 - <<'PY'
|
|
216
|
+
from pathlib import Path
|
|
217
|
+
import os
|
|
218
|
+
|
|
219
|
+
remote_env = Path(os.environ["REMOTE_DIR"]) / ".agent-playground.env"
|
|
220
|
+
source_env = Path("/opt/nightpay/.agent-playground.env")
|
|
221
|
+
if not remote_env.exists() or not source_env.exists():
|
|
222
|
+
raise SystemExit(0)
|
|
223
|
+
|
|
224
|
+
def parse(lines):
|
|
225
|
+
out = {}
|
|
226
|
+
for line in lines:
|
|
227
|
+
if not line.startswith("export "):
|
|
228
|
+
continue
|
|
229
|
+
if "=" not in line:
|
|
230
|
+
continue
|
|
231
|
+
key, value = line.split("=", 1)
|
|
232
|
+
key = key.replace("export ", "", 1).strip()
|
|
233
|
+
out[key] = value.strip().strip('"').strip("'")
|
|
234
|
+
return out
|
|
235
|
+
|
|
236
|
+
def is_placeholder(value: str) -> bool:
|
|
237
|
+
if not value:
|
|
238
|
+
return True
|
|
239
|
+
lowered = value.lower()
|
|
240
|
+
return ("<fill-in" in lowered) or (value == "your-key")
|
|
241
|
+
|
|
242
|
+
remote_lines = remote_env.read_text().splitlines()
|
|
243
|
+
source_lines = source_env.read_text().splitlines()
|
|
244
|
+
remote_vals = parse(remote_lines)
|
|
245
|
+
source_vals = parse(source_lines)
|
|
246
|
+
|
|
247
|
+
remote_key = remote_vals.get("MASUMI_API_KEY", "")
|
|
248
|
+
source_key = source_vals.get("MASUMI_API_KEY", "")
|
|
249
|
+
|
|
250
|
+
if not is_placeholder(remote_key):
|
|
251
|
+
raise SystemExit(0)
|
|
252
|
+
if is_placeholder(source_key):
|
|
253
|
+
raise SystemExit(0)
|
|
254
|
+
|
|
255
|
+
updated = False
|
|
256
|
+
out = []
|
|
257
|
+
for line in remote_lines:
|
|
258
|
+
if line.startswith("export MASUMI_API_KEY="):
|
|
259
|
+
out.append(f'export MASUMI_API_KEY="{source_key}"')
|
|
260
|
+
updated = True
|
|
261
|
+
else:
|
|
262
|
+
out.append(line)
|
|
263
|
+
if not updated:
|
|
264
|
+
out.append(f'export MASUMI_API_KEY="{source_key}"')
|
|
265
|
+
|
|
266
|
+
remote_env.write_text("\n".join(out) + "\n")
|
|
267
|
+
PY
|
|
268
|
+
chown deploy:deploy "$REMOTE_DIR/.agent-playground.env" || true
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
if [[ -n "${UI_PORT:-}" || -n "${MIP_PORT:-}" ]]; then
|
|
272
|
+
python3 - <<'PY'
|
|
273
|
+
from pathlib import Path
|
|
274
|
+
import os
|
|
275
|
+
|
|
276
|
+
env_path = Path(os.environ["REMOTE_DIR"]) / ".agent-playground.env"
|
|
277
|
+
if not env_path.exists():
|
|
278
|
+
raise SystemExit(f"Missing env file: {env_path}")
|
|
279
|
+
|
|
280
|
+
ui_port = os.environ.get("UI_PORT", "").strip()
|
|
281
|
+
mip_port = os.environ.get("MIP_PORT", "").strip()
|
|
282
|
+
updates = {}
|
|
283
|
+
if ui_port:
|
|
284
|
+
updates["export UI_PORT"] = f"\"{ui_port}\""
|
|
285
|
+
if mip_port:
|
|
286
|
+
updates["export MIP_PORT"] = f"\"{mip_port}\""
|
|
287
|
+
|
|
288
|
+
if updates:
|
|
289
|
+
lines = env_path.read_text().splitlines()
|
|
290
|
+
out = []
|
|
291
|
+
seen = set()
|
|
292
|
+
for line in lines:
|
|
293
|
+
replaced = False
|
|
294
|
+
for key, value in updates.items():
|
|
295
|
+
if line.startswith(key + "="):
|
|
296
|
+
out.append(f"{key}={value}")
|
|
297
|
+
seen.add(key)
|
|
298
|
+
replaced = True
|
|
299
|
+
break
|
|
300
|
+
if not replaced:
|
|
301
|
+
out.append(line)
|
|
302
|
+
for key, value in updates.items():
|
|
303
|
+
if key not in seen:
|
|
304
|
+
out.append(f"{key}={value}")
|
|
305
|
+
env_path.write_text("\n".join(out) + "\n")
|
|
306
|
+
PY
|
|
307
|
+
chown deploy:deploy "$REMOTE_DIR/.agent-playground.env" || true
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
su - deploy -c "cd '$REMOTE_DIR' && bash scripts/agent-playground-setup.sh stop || true"
|
|
311
|
+
|
|
312
|
+
# Best-effort cleanup for stale processes that survived previous stop operations.
|
|
313
|
+
pkill -u deploy -f "$REMOTE_DIR/skills/nightpay/scripts/mip003-server.sh" || true
|
|
314
|
+
pkill -u deploy -f "$REMOTE_DIR/ui/node_modules/.bin/vite" || true
|
|
315
|
+
rm -f "$REMOTE_DIR/.agent-playground/run/"*.pid || true
|
|
316
|
+
|
|
317
|
+
mip_port="${MIP_PORT:-8090}"
|
|
318
|
+
ui_port="${UI_PORT:-3333}"
|
|
319
|
+
|
|
320
|
+
# Kill stale listeners by port to avoid bind conflicts on restart.
|
|
321
|
+
if command -v ss >/dev/null 2>&1; then
|
|
322
|
+
for port in "$mip_port" "$ui_port"; do
|
|
323
|
+
pids="$(ss -ltnp "( sport = :$port )" 2>/dev/null | awk -F'pid=' 'NR>1 {split($2,a,","); print a[1]}' | sort -u)"
|
|
324
|
+
if [[ -n "$pids" ]]; then
|
|
325
|
+
kill $pids || true
|
|
326
|
+
sleep 1
|
|
327
|
+
pids_after="$(ss -ltnp "( sport = :$port )" 2>/dev/null | awk -F'pid=' 'NR>1 {split($2,a,","); print a[1]}' | sort -u)"
|
|
328
|
+
if [[ -n "$pids_after" ]]; then
|
|
329
|
+
kill -9 $pids_after || true
|
|
330
|
+
fi
|
|
331
|
+
fi
|
|
332
|
+
done
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
# Clear Vite caches to avoid stale file metadata and permission drift after sync.
|
|
336
|
+
rm -rf "$REMOTE_DIR/ui/.vite" "$REMOTE_DIR/ui/node_modules/.vite" || true
|
|
337
|
+
|
|
338
|
+
su - deploy -c "cd '$REMOTE_DIR' && bash scripts/agent-playground-setup.sh start"
|
|
339
|
+
su - deploy -c "cd '$REMOTE_DIR' && bash scripts/agent-playground-setup.sh doctor"
|
|
340
|
+
REMOTE
|
|
341
|
+
|
|
342
|
+
if [[ "$SKIP_PROOF_RECREATE" == "1" ]]; then
|
|
343
|
+
echo "[7/9] Skipping proof-server recreate (--skip-proof-recreate)."
|
|
344
|
+
else
|
|
345
|
+
echo "[7/9] Recreate proof-server Docker stack..."
|
|
346
|
+
ssh "${SSH_OPTS[@]}" "root@${HOST}" \
|
|
347
|
+
"BRIDGE_DIR='${BRIDGE_DIR}' bash -s" <<'REMOTE'
|
|
348
|
+
set -euo pipefail
|
|
349
|
+
|
|
350
|
+
if [[ ! -f "$BRIDGE_DIR/docker-compose.yml" ]]; then
|
|
351
|
+
echo "bridge compose not found at $BRIDGE_DIR; skipping proof-server recreate"
|
|
352
|
+
exit 0
|
|
353
|
+
fi
|
|
354
|
+
|
|
355
|
+
cd "$BRIDGE_DIR"
|
|
356
|
+
docker compose pull || true
|
|
357
|
+
|
|
358
|
+
if ! docker compose up -d --force-recreate --pull never; then
|
|
359
|
+
if ! docker image inspect ghcr.io/midnight-ntwrk/proof-server:4.0.0 >/dev/null 2>&1 \
|
|
360
|
+
&& docker image inspect midnightnetwork/proof-server:latest >/dev/null 2>&1; then
|
|
361
|
+
docker tag midnightnetwork/proof-server:latest ghcr.io/midnight-ntwrk/proof-server:4.0.0
|
|
362
|
+
fi
|
|
363
|
+
docker compose up -d --force-recreate --pull never
|
|
364
|
+
fi
|
|
365
|
+
REMOTE
|
|
366
|
+
fi
|
|
367
|
+
|
|
368
|
+
if [[ "$SKIP_MASUMI_RECREATE" == "1" ]]; then
|
|
369
|
+
echo "[8/9] Skipping Masumi recreate (--skip-masumi-recreate)."
|
|
370
|
+
else
|
|
371
|
+
echo "[8/9] Recreate Masumi API containers..."
|
|
372
|
+
ssh "${SSH_OPTS[@]}" "root@${HOST}" \
|
|
373
|
+
"MASUMI_DIR='${MASUMI_DIR}' bash -s" <<'REMOTE'
|
|
374
|
+
set -euo pipefail
|
|
375
|
+
|
|
376
|
+
if [[ ! -f "$MASUMI_DIR/docker-compose.yml" ]]; then
|
|
377
|
+
echo "masumi compose not found at $MASUMI_DIR; skipping Masumi recreate"
|
|
378
|
+
exit 0
|
|
379
|
+
fi
|
|
380
|
+
|
|
381
|
+
cd "$MASUMI_DIR"
|
|
382
|
+
|
|
383
|
+
# Keep DB volumes stable; only recreate API containers unless DB services are down.
|
|
384
|
+
docker compose up -d postgres-payment postgres-registry
|
|
385
|
+
docker compose pull payment-service registry-service || true
|
|
386
|
+
docker compose up -d --no-deps --force-recreate payment-service registry-service
|
|
387
|
+
|
|
388
|
+
for i in $(seq 1 90); do
|
|
389
|
+
p="$(curl -fsS -m 2 http://localhost:3001/api/v1/health || true)"
|
|
390
|
+
r="$(curl -fsS -m 2 http://localhost:3000/api/v1/health || true)"
|
|
391
|
+
if [[ -n "$p" && -n "$r" ]]; then
|
|
392
|
+
echo "masumi_payment=$p"
|
|
393
|
+
echo "masumi_registry=$r"
|
|
394
|
+
exit 0
|
|
395
|
+
fi
|
|
396
|
+
sleep 2
|
|
397
|
+
done
|
|
398
|
+
|
|
399
|
+
echo "ERROR: Masumi health check failed after recreate." >&2
|
|
400
|
+
docker compose ps >&2
|
|
401
|
+
docker compose logs --tail 80 payment-service registry-service >&2
|
|
402
|
+
exit 1
|
|
403
|
+
REMOTE
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
MIP_PORT_CHECK="${MIP_PORT:-8090}"
|
|
407
|
+
UI_PORT_CHECK="${UI_PORT:-3333}"
|
|
408
|
+
|
|
409
|
+
echo "[9/9] Final health checks..."
|
|
410
|
+
run_ssh "\
|
|
411
|
+
set -euo pipefail; \
|
|
412
|
+
ui_enabled='1'; \
|
|
413
|
+
if [[ -f '${REMOTE_DIR}/.agent-playground.env' ]]; then source '${REMOTE_DIR}/.agent-playground.env'; ui_enabled=\${ENABLE_UI:-1}; fi; \
|
|
414
|
+
echo -n 'mip='; curl -fsS http://localhost:${MIP_PORT_CHECK}/availability; echo; \
|
|
415
|
+
if [[ \"\$ui_enabled\" == '1' && -f '${REMOTE_DIR}/ui/package.json' ]]; then \
|
|
416
|
+
ui_code=\$(curl -sS -o /dev/null -w '%{http_code}' http://localhost:${UI_PORT_CHECK}/); \
|
|
417
|
+
echo ui_status=\$ui_code; \
|
|
418
|
+
if [[ \"\$ui_code\" != '200' ]]; then echo 'ERROR: UI health check failed' >&2; exit 1; fi; \
|
|
419
|
+
else \
|
|
420
|
+
echo 'ui_status=skipped'; \
|
|
421
|
+
fi; \
|
|
422
|
+
if [[ '${SKIP_MASUMI_RECREATE}' != '1' && -f '${MASUMI_DIR}/docker-compose.yml' ]]; then \
|
|
423
|
+
echo -n 'payment='; curl -fsS http://localhost:3001/api/v1/health; echo; \
|
|
424
|
+
echo -n 'registry='; curl -fsS http://localhost:3000/api/v1/health; echo; \
|
|
425
|
+
fi; \
|
|
426
|
+
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'"
|
|
427
|
+
|
|
428
|
+
echo "Deploy completed successfully."
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "nightpay",
|
|
3
|
+
"name": "NightPay",
|
|
4
|
+
"description": "Anonymous community bounty pools \u2014 Midnight ZK proofs + Masumi settlement + Cardano finality. Skills auto-loaded from skills/nightpay/.",
|
|
5
|
+
"version": "0.3.11",
|
|
6
|
+
"configSchema": {},
|
|
7
|
+
"skills": [
|
|
8
|
+
"skills/nightpay"
|
|
9
|
+
]
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nightpay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Anonymous community bounties for AI agents. Midnight ZK proofs + Masumi settlement + Cardano finality.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bounties",
|
|
@@ -21,14 +21,16 @@
|
|
|
21
21
|
"type": "git",
|
|
22
22
|
"url": "git+https://github.com/nightpay/nightpay.git"
|
|
23
23
|
},
|
|
24
|
-
"license": "
|
|
24
|
+
"license": "AGPL-3.0-only",
|
|
25
25
|
"author": "nightpay contributors",
|
|
26
26
|
"type": "module",
|
|
27
27
|
"bin": {
|
|
28
28
|
"nightpay": "bin/cli.js"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
|
-
"test": "
|
|
31
|
+
"test": "node test/run-quality-gate.mjs",
|
|
32
|
+
"test:quality": "node test/run-quality-gate.mjs",
|
|
33
|
+
"test:smoke": "node test/run-smoke-test.mjs"
|
|
32
34
|
},
|
|
33
35
|
"files": [
|
|
34
36
|
"bin/",
|
|
@@ -36,6 +38,14 @@
|
|
|
36
38
|
"README.md",
|
|
37
39
|
"LICENSE",
|
|
38
40
|
"nightpay_sdk.py",
|
|
39
|
-
"scripts/"
|
|
40
|
-
|
|
41
|
+
"scripts/",
|
|
42
|
+
"plugin.js",
|
|
43
|
+
"openclaw.plugin.json"
|
|
44
|
+
],
|
|
45
|
+
"openclaw": {
|
|
46
|
+
"extensions": [
|
|
47
|
+
"./plugin.js"
|
|
48
|
+
],
|
|
49
|
+
"type": "skillBundle"
|
|
50
|
+
}
|
|
41
51
|
}
|