Files
openclaw-backups/skills/clawdtalk-client/scripts/connect.sh

331 lines
9.8 KiB
Bash

#!/bin/bash
#
# ClawdTalk - WebSocket Connection Manager
#
# Manages the WebSocket connection to ClawdTalk server for receiving
# voice transcriptions and sending responses.
# Works with both Clawdbot and OpenClaw.
#
# Usage: ./connect.sh {start|stop|status|restart} [--server <url>]
#
# Env vars: via .env
# Endpoints: none (launches ws-client.js)
# Reads: skill-config.json, .env
# Writes: .connect.pid, .connect.log
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
CONFIG_FILE="$SKILL_DIR/skill-config.json"
PID_FILE="$SKILL_DIR/.connect.pid"
LOG_FILE="$SKILL_DIR/.connect.log"
# Parse server override from args
SERVER_FLAG=""
while [[ $# -gt 0 ]]; do
case "$1" in
--server)
SERVER_FLAG="--server $2"
shift 2
;;
*)
CMD="${CMD:-$1}"
shift
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_status() {
echo -e "${BLUE}📞 Clawd Talk Connection Manager${NC}"
echo "================================="
echo ""
}
check_config() {
if [ ! -f "$CONFIG_FILE" ]; then
echo -e "${RED}❌ Configuration not found. Run './setup.sh' first.${NC}"
exit 1
fi
# Check if we have API key
local api_key=$(jq -r '.api_key // empty' "$CONFIG_FILE" 2>/dev/null || echo "")
if [ -z "$api_key" ] || [ "$api_key" = "null" ] || [ "$api_key" = "YOUR_API_KEY_HERE" ]; then
echo -e "${RED}❌ No API key configured.${NC}"
echo ""
echo "Get your API key from https://clawdtalk.com → Dashboard"
echo "Then add it to skill-config.json"
exit 1
fi
}
check_gateway_tools() {
# Check if sessions_send is allowed on the gateway /tools/invoke endpoint
# Without this, the voice assistant can't proxy questions to the Clawdbot
local config_paths=(
"$HOME/.openclaw/openclaw.json"
"$HOME/.clawdbot/clawdbot.json"
)
for cfg in "${config_paths[@]}"; do
if [ -f "$cfg" ]; then
local tools_allow=$(jq -r '.gateway.tools.allow // [] | join(",")' "$cfg" 2>/dev/null)
if [ -z "$tools_allow" ] || ! echo "$tools_allow" | grep -q "sessions_send"; then
echo -e "${YELLOW}⚠️ Gateway missing 'sessions_send' in tools allowlist${NC}"
echo ""
echo " The voice assistant needs sessions_send to proxy questions to your Clawdbot."
echo " Add it to your config ($cfg):"
echo ""
echo ' "gateway": { "tools": { "allow": ["sessions_send"] } }'
echo ""
echo " Or ask your Clawdbot to run:"
echo " openclaw config set gateway.tools.allow '[\"sessions_send\"]'"
echo ""
return 1
fi
return 0
fi
done
echo -e "${YELLOW}⚠️ No OpenClaw/Clawdbot config found. Gateway tools check skipped.${NC}"
return 0
}
check_dependencies() {
for tool in node jq; do
if ! command -v "$tool" &> /dev/null; then
echo -e "${RED}❌ Required tool '$tool' is not installed.${NC}"
exit 1
fi
done
# Check node_modules exist
if [ ! -d "$SKILL_DIR/node_modules/ws" ]; then
echo -e "${YELLOW}📦 Installing dependencies...${NC}"
(cd "$SKILL_DIR" && npm install --production 2>/dev/null)
if [ ! -d "$SKILL_DIR/node_modules/ws" ]; then
echo -e "${RED}❌ Failed to install dependencies. Run 'npm install' in $SKILL_DIR${NC}"
exit 1
fi
echo -e " ${GREEN}✓ Dependencies installed${NC}"
fi
}
is_running() {
if [ -f "$PID_FILE" ]; then
local pid=$(cat "$PID_FILE")
if ps -p "$pid" &> /dev/null; then
return 0
else
# Stale PID file
rm -f "$PID_FILE"
return 1
fi
fi
return 1
}
start_connection() {
if is_running; then
echo -e "${YELLOW}⚠️ Connection already running (PID: $(cat "$PID_FILE"))${NC}"
return 0
fi
echo "🚀 Starting WebSocket connection..."
# Source skill's own .env if it exists (for skill-specific env vars only)
[ -f "$SKILL_DIR/.env" ] && . "$SKILL_DIR/.env"
# Rotate log if it's too big (> 1MB)
if [ -f "$LOG_FILE" ] && [ $(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null || echo 0) -gt 1048576 ]; then
echo "🔄 Rotating large log file..."
mv "$LOG_FILE" "${LOG_FILE}.1" 2>/dev/null || true
fi
# Start the WebSocket client in background (append to log)
nohup node "$SCRIPT_DIR/ws-client.js" $SERVER_FLAG >> "$LOG_FILE" 2>&1 &
local pid=$!
echo $pid > "$PID_FILE"
# Give it a moment to start
sleep 2
# Check if it's still running
if ps -p "$pid" &> /dev/null; then
echo -e "${GREEN}WebSocket client started (PID: $pid)${NC}"
echo ""
echo "Use './scripts/connect.sh status' to check connection health"
echo "Logs: $LOG_FILE"
else
rm -f "$PID_FILE"
echo -e "${RED}Failed to start WebSocket client${NC}"
echo ""
echo "Check logs: $LOG_FILE"
exit 1
fi
}
stop_connection() {
if ! is_running; then
echo -e "${YELLOW}⚠️ Connection not running${NC}"
return 0
fi
local pid=$(cat "$PID_FILE")
echo "🛑 Stopping WebSocket connection (PID: $pid)..."
# Try graceful shutdown first
if kill "$pid" 2>/dev/null; then
# Wait up to 5 seconds for graceful shutdown
for i in {1..5}; do
if ! ps -p "$pid" &> /dev/null; then
break
fi
sleep 1
done
# Force kill if still running
if ps -p "$pid" &> /dev/null; then
kill -9 "$pid" 2>/dev/null || true
fi
fi
rm -f "$PID_FILE"
echo -e "${GREEN}WebSocket client stopped${NC}"
}
show_status() {
print_status
if is_running; then
local pid=$(cat "$PID_FILE")
echo -e "Status: ${GREEN}CONNECTED${NC} (PID: $pid)"
# Show recent log lines
if [ -f "$LOG_FILE" ]; then
echo ""
echo "Recent activity:"
echo "================"
tail -n 5 "$LOG_FILE" 2>/dev/null | while IFS= read -r line; do
echo " $line"
done
fi
else
echo -e "Status: ${RED}DISCONNECTED${NC}"
if [ -f "$LOG_FILE" ]; then
echo ""
echo "Last error (if any):"
echo "==================="
tail -n 3 "$LOG_FILE" 2>/dev/null | while IFS= read -r line; do
if [[ "$line" =~ (ERROR|Error|error|FAILED|Failed|failed) ]]; then
echo -e " ${RED}$line${NC}"
else
echo " $line"
fi
done
fi
fi
# Check gateway tools
echo ""
check_gateway_tools 2>/dev/null && echo -e "Gateway tools: ${GREEN}sessions_send allowed${NC}" || true
echo ""
echo "Configuration:"
echo "============="
local server_url=$(jq -r '.server // "https://clawdtalk.com"' "$CONFIG_FILE" 2>/dev/null)
echo " Server: $server_url"
echo ""
echo "Commands:"
echo "========="
echo " start - Start WebSocket connection"
echo " stop - Stop WebSocket connection"
echo " restart - Restart WebSocket connection"
echo " status - Show this status"
echo " watchdog - Check if running and restart if needed"
echo ""
echo "Flags:"
echo " --server <url> - Override server URL"
echo ""
}
restart_connection() {
echo "🔄 Restarting WebSocket connection..."
stop_connection
sleep 1
start_connection
}
watchdog_check() {
# Silent watchdog - only log when taking action
if ! is_running; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WATCHDOG: Process not running, restarting..." >> "$SKILL_DIR/.watchdog.log"
check_config 2>/dev/null || {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WATCHDOG: Config check failed, skipping restart" >> "$SKILL_DIR/.watchdog.log"
return 1
}
check_dependencies 2>/dev/null || {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WATCHDOG: Dependencies check failed, skipping restart" >> "$SKILL_DIR/.watchdog.log"
return 1
}
start_connection >> "$SKILL_DIR/.watchdog.log" 2>&1
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WATCHDOG: Restart completed" >> "$SKILL_DIR/.watchdog.log"
fi
}
# Main command handling
case "${CMD:-}" in
start)
print_status
check_config
check_dependencies
check_gateway_tools || true
start_connection
;;
stop)
print_status
stop_connection
;;
restart)
print_status
check_config
check_dependencies
check_gateway_tools || true
restart_connection
;;
status)
check_config
show_status
;;
watchdog)
# Silent watchdog mode - used by cron
watchdog_check
;;
*)
print_status
echo -e "${RED}❌ Invalid command${NC}"
echo ""
echo "Usage: $0 {start|stop|status|restart|watchdog} [--server <url>]"
echo ""
echo "Commands:"
echo " start - Start WebSocket connection to ClawdTalk server"
echo " stop - Stop WebSocket connection"
echo " restart - Restart WebSocket connection"
echo " status - Show connection status and configuration"
echo " watchdog - Check if running and restart if needed (for cron)"
echo ""
echo "Flags:"
echo " --server <url> - Override server URL"
exit 1
;;
esac