Skip to content

Commit 3838b3f

Browse files
authored
test(kiloclaw): assert Kilo Chat plugin in smoke tests (#3501)
* test(kiloclaw): assert kilo chat plugin in smokes * test(kiloclaw): use semantic kilo chat smoke probe * test(kiloclaw): avoid temp file in smoke probe
1 parent abd04a7 commit 3838b3f

3 files changed

Lines changed: 135 additions & 0 deletions

File tree

services/kiloclaw/scripts/controller-entrypoint-smoke-test.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ IMAGE="${IMAGE:-kiloclaw:controller}"
99
TOKEN="${TOKEN:-smoke-token}"
1010
PORT="${PORT:-18790}"
1111
KILOCODE_API_KEY="${KILOCODE_API_KEY:-smoke-kilocode-key}"
12+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13+
14+
source "$SCRIPT_DIR/controller-smoke-helpers.sh"
1215

1316
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
1417
echo "Image '$IMAGE' is not available locally."
@@ -116,6 +119,8 @@ CODE=$(curl -s -o /dev/null -w "%{http_code}" \
116119
"http://127.0.0.1:${PORT}/_kilo/gateway/status")
117120
check "gateway status (bearer auth) -> 200" "200" "$CODE"
118121

122+
assert_kilo_chat_smoke "$CID" "$PORT" "$TOKEN"
123+
119124
echo
120125
echo "--- proxy token ---"
121126

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env bash
2+
3+
# Shared assertions for KiloClaw controller image smoke scripts.
4+
# Expects the caller to define a `check <label> <expected> <actual>` function.
5+
6+
assert_kilo_chat_config_patched() {
7+
local cid="$1"
8+
local details
9+
10+
if details=$(docker exec -i "$cid" python3 - <<'PY' 2>&1
11+
import json
12+
from pathlib import Path
13+
14+
config_path = Path('/root/.openclaw/openclaw.json')
15+
doc = json.loads(config_path.read_text())
16+
channel = doc.get('channels', {}).get('kilo-chat', {})
17+
plugins = doc.get('plugins', {})
18+
entries = plugins.get('entries', {})
19+
load = plugins.get('load', {})
20+
paths = load.get('paths', [])
21+
expected_path = '/usr/local/lib/node_modules/@kiloclaw/kilo-chat'
22+
23+
checks = [
24+
('channels.kilo-chat.enabled', channel.get('enabled') is True),
25+
('channels.kilo-chat._configured', channel.get('_configured') is True),
26+
('plugins.load.paths includes kilo-chat', expected_path in paths),
27+
('plugins.entries.kilo-chat.enabled', entries.get('kilo-chat', {}).get('enabled') is True),
28+
]
29+
failed = [name for name, ok in checks if not ok]
30+
if failed:
31+
raise SystemExit('missing/invalid: ' + ', '.join(failed))
32+
print('ok')
33+
PY
34+
); then
35+
check "kilo-chat config patched" "ok" "$details"
36+
else
37+
check "kilo-chat config patched" "ok" "failed"
38+
echo " details: $details"
39+
fi
40+
}
41+
42+
assert_kilo_chat_plugin_loaded() {
43+
local cid="$1"
44+
local plugin_json
45+
local details
46+
47+
if ! plugin_json=$(docker exec "$cid" openclaw plugins inspect kilo-chat --json 2>&1); then
48+
check "kilo-chat plugin inspect" "loaded" "failed"
49+
echo " output: $plugin_json"
50+
return
51+
fi
52+
53+
if details=$(python3 -c '
54+
import json
55+
import sys
56+
57+
doc = json.load(sys.stdin)
58+
plugin = doc.get("plugin", {})
59+
status = plugin.get("status")
60+
error = plugin.get("error")
61+
route_count = doc.get("httpRouteCount", 0)
62+
if status != "loaded":
63+
raise SystemExit(f"status={status!r}")
64+
if error:
65+
raise SystemExit(f"error={error!r}")
66+
if not isinstance(route_count, int) or route_count < 1:
67+
raise SystemExit(f"httpRouteCount={route_count!r}")
68+
print("loaded")
69+
' <<< "$plugin_json" 2>&1); then
70+
check "kilo-chat plugin inspect" "loaded" "$details"
71+
else
72+
check "kilo-chat plugin inspect" "loaded" "failed"
73+
echo " details: $details"
74+
echo " output: $plugin_json"
75+
fi
76+
}
77+
78+
assert_kilo_chat_webhook_route() {
79+
local port="$1"
80+
local token="$2"
81+
local response
82+
local body
83+
local code
84+
local body_check
85+
86+
response=$(curl -sS -w "\n%{http_code}" \
87+
-X POST \
88+
-H "x-kiloclaw-proxy-token: $token" \
89+
-H "Authorization: Bearer $token" \
90+
-H "Content-Type: application/json" \
91+
--data '{"type":"smoke.probe"}' \
92+
"http://127.0.0.1:${port}/plugins/kilo-chat/webhook" 2>/dev/null || true)
93+
code="${response##*$'\n'}"
94+
body="${response%$'\n'*}"
95+
96+
check "kilo-chat webhook unknown event -> 400" "400" "$code"
97+
98+
if body_check=$(python3 -c '
99+
import json
100+
import sys
101+
102+
doc = json.loads(sys.stdin.read())
103+
if doc.get("error") != "Unknown webhook type":
104+
raise SystemExit(doc)
105+
print("Unknown webhook type")
106+
' <<< "$body" 2>&1); then
107+
check "kilo-chat webhook error body" "Unknown webhook type" "$body_check"
108+
else
109+
check "kilo-chat webhook error body" "Unknown webhook type" "failed"
110+
echo " details: $body_check"
111+
echo " body: $body"
112+
fi
113+
}
114+
115+
assert_kilo_chat_smoke() {
116+
local cid="$1"
117+
local port="$2"
118+
local token="$3"
119+
120+
echo
121+
echo "--- kilo-chat plugin ---"
122+
assert_kilo_chat_config_patched "$cid"
123+
assert_kilo_chat_plugin_loaded "$cid"
124+
assert_kilo_chat_webhook_route "$port" "$token"
125+
}

services/kiloclaw/scripts/controller-smoke-test.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ set -euo pipefail
1010
IMAGE="${IMAGE:-kiloclaw:controller}"
1111
TOKEN="${TOKEN:-smoke-token}"
1212
PORT="${PORT:-18789}"
13+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14+
15+
source "$SCRIPT_DIR/controller-smoke-helpers.sh"
1316

1417
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
1518
echo "Image '$IMAGE' is not available locally."
@@ -91,6 +94,8 @@ CODE=$(curl -s -o /dev/null -w "%{http_code}" \
9194
"http://127.0.0.1:${PORT}/_kilo/gateway/status")
9295
check "gateway status (bearer auth) -> 200" "200" "$CODE"
9396

97+
assert_kilo_chat_smoke "$CID" "$PORT" "$TOKEN"
98+
9499
echo
95100
echo "--- proxy token ---"
96101

0 commit comments

Comments
 (0)