File size: 5,197 Bytes
b26f525
 
c0963c0
b26f525
 
 
c0963c0
b26f525
 
 
 
 
c0963c0
b26f525
 
 
 
 
 
 
 
 
c0963c0
b26f525
 
 
 
 
 
 
 
 
 
 
 
c0963c0
b26f525
 
 
 
c0963c0
b26f525
 
a262fdc
b26f525
 
 
 
 
 
 
 
c0963c0
b26f525
 
 
 
c0963c0
b26f525
 
 
 
 
 
 
 
 
 
c0963c0
b26f525
 
 
 
23039bf
 
 
 
 
 
c0963c0
f7cacc8
 
 
fa8d364
c0963c0
b26f525
 
c0963c0
a262fdc
b26f525
a262fdc
 
a6b7d4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432fbd9
88904b4
 
 
 
 
6c137b9
2d09bf1
 
 
8a7082c
88904b4
8a7082c
2d09bf1
8a7082c
 
88904b4
8a7082c
 
7e7b0d5
a262fdc
7e7b0d5
a262fdc
 
 
 
2cf0f39
a262fdc
 
2cf0f39
a262fdc
 
 
 
 
c0963c0
a262fdc
 
 
 
c0963c0
a262fdc
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/bin/bash

# Centralized Logging Configuration
export LOG_LEVEL=${LOG_LEVEL:-"info"}
export LOG_FILE=${LOG_FILE:-"/app/verdant_claw.log"}

# Mask sensitive env vars in logs
log() {
  local msg=$(echo "$1" | sed -E 's/(nvapi|sk|gsk)[a-zA-Z0-9]+/\1*****/g')
  echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] [$LOG_LEVEL] $msg" | tee -a $LOG_FILE
}

# Trap SIGTERM for graceful shutdown
cleanup() {
  log "Shutting down services gracefully..."
  kill $(jobs -p) 2>/dev/null
  sleep 2
  log "Shutdown complete"
  exit 0
}
trap cleanup SIGTERM SIGINT

# Parse API_KEYS_JSON secret
if [ -n "$API_KEYS_JSON" ]; then
  log "Parsing API keys from JSON..."
  export NVIDIA_API_KEY=$(echo $API_KEYS_JSON | jq -r '.nvidia // empty')
  export OPENAI_API_KEY=$(echo $API_KEYS_JSON | jq -r '.openai // empty')
  export ANTHROPIC_API_KEY=$(echo $API_KEYS_JSON | jq -r '.anthropic // empty')
  export GOOGLE_API_KEY=$(echo $API_KEYS_JSON | jq -r '.google // empty')
  export GROQ_API_KEY=$(echo $API_KEYS_JSON | jq -r '.groq // empty')
  log "βœ“ API keys loaded from JSON"
else
  log "⚠️ WARNING: API_KEYS_JSON not set!"
fi

# Function to start service with retry
start_with_retry() {
  local name=$1
  local cmd=$2
  local max_attempts=3

  for i in $(seq 1 $max_attempts); do
    log "Starting $name (attempt $i/$max_attempts)..."
    eval "$cmd" &
    local pid=$!
    sleep 5
    if ps -p $pid > /dev/null; then
      log "βœ“ $name started (PID: $pid)"
      return 0
    fi
    log "⚠️ $name failed to start, retrying..."
  done

  log "❌ ERROR: $name failed after $max_attempts attempts"
  return 1
}

# Check if ports are available
check_port() {
  local port=$1
  if netstat -tlnp 2>/dev/null | grep -q ":$port"; then
    log "❌ ERROR: Port $port already in use!"
    return 1
  fi
  return 0
}

log "Verifying infrastructure ports..."
for port in 7860 7861 7687 20128 7862; do
  check_port $port || exit 1
done

# πŸš€ Start Services
MEMGRAPH_BIN=$(command -v memgraph || echo "/usr/bin/memgraph")
if [ ! -f "$MEMGRAPH_BIN" ]; then
  MEMGRAPH_BIN="/usr/lib/memgraph/memgraph"
fi

start_with_retry "Memgraph" "$MEMGRAPH_BIN --bolt-port 7687" || exit 1

# Start ZeroClaw on port 42617 (NOT 7860 - Marimo needs that)
# Use environment variable to set port
export ZEROCLAW_GATEWAY_PORT=42617
start_with_retry "ZeroClaw" "zeroclaw gateway" || exit 1

start_with_retry "OmniRoute" "node /app/scripts/omniroute.js --config /app/config/omniroute-masterfile.json --port 20128" || exit 1

# Start Graph Viewer on port 7861
GRAPH_VIEWER_PORT=7861 start_with_retry "Graph Viewer" "node /app/scripts/graph-viewer.js" || exit 1

log "All infrastructure ready! Launching Marimo UI on port 7860..."

# Setup Ollama config (proxy to ZeroClaw)
mkdir -p /home/node/.ollama
cp /app/ollama-config.json /home/node/.ollama/config.json 2>/dev/null || true
log "βœ“ Ollama configured to proxy to ZeroClaw"

# Start Ollama serve (in background)
log "Starting Ollama..."
nohup ollama serve > /tmp/ollama.log 2>&1 &
OLLAMA_PID=$!
sleep 3
if ps -p $OLLAMA_PID > /dev/null; then
  log "βœ“ Ollama started (PID: $OLLAMA_PID)"
  # Pull a default model
  log "Pulling default model (this may take a minute)..."
  ollama pull llama3.2 || log "⚠️ Could not pull model, will use ZeroClaw models"
else
  log "⚠️ Ollama failed to start"
fi

# Setup Marimo config (pre-configured with Ollama as AI provider)
mkdir -p /home/node/.config/marimo
cat > /home/node/.config/marimo/marimo.toml << 'TOML'
[ai]
enabled = true

[ai.providers.ollama]
name = "Ollama"
base_url = "http://localhost:11434/v1"
api_key = "ollama-local-key"

[[ai.models]]
provider = "ollama"
model = "zeroclaw/default"
TOML
log "βœ“ Marimo AI config created with Ollama provider"

# Initialize Pi (accepts config, creates necessary files)
log "Initializing Pi agent..."
echo "y" | pi --mode rpc --extensions /app/agent-pi/pi-extensions --skills /app/agent-pi/skills --prompts /app/agent-pi/commands </dev/null > /tmp/pi-init.log 2>&1 || true
sleep 2

# Start pi-acp for ACP support (Marimo AI integration) through stdio-to-ws bridge
# Name it "opencode" so Marimo recognizes it!
log "Starting pi-acp ACP server via stdio-to-ws bridge (as 'opencode')..."
nohup npx stdio-to-ws "pi-acp --terminal-login" --port 3017 --name "opencode" > /tmp/pi-acp.log 2>&1 &
PI_ACP_PID=$!
sleep 3
if ps -p $PI_ACP_PID > /dev/null; then
  log "βœ“ pi-acp started on ws://localhost:3017 as 'opencode' (PID: $PI_ACP_PID)"
else
  log "⚠️ pi-acp failed to start, check /tmp/pi-acp.log"
  cat /tmp/pi-acp.log
fi

# Launch Marimo in EDIT MODE (not app mode)
cd /app
nohup marimo edit app.py --host 0.0.0.0 --port 7860 --no-token > /tmp/marimo.log 2>&1 &
MARIMO_PID=$!
sleep 3
if ps -p $MARIMO_PID > /dev/null; then
  log "βœ“ Marimo started (PID: $MARIMO_PID)"
  log "  Marimo logs: /tmp/marimo.log"
else
  log "❌ ERROR: Marimo failed to start!"
  cat /tmp/marimo.log
  exit 1
fi

log "All services active!"
log "  - Memgraph: port 7687"
log "  - ZeroClaw: port 7862"
log "  - OmniRoute: port 20128"
log "  - Graph Viewer: port 7861"
log "  - Marimo UI: port 7860 (primary)"

# Keep container alive
log "Holding container open. Access the UI at https://your-space.hf.space"
wait