-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell-install.sh
More file actions
executable file
·273 lines (242 loc) · 10.3 KB
/
shell-install.sh
File metadata and controls
executable file
·273 lines (242 loc) · 10.3 KB
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#!/bin/bash
# shell-install.sh — Interactive setup for nova-memory
# Human-facing entry point that ensures all config is in place, then execs agent-install.sh.
#
# Flow:
# 1. Source lib/pg-env.sh (early — makes load_pg_env() available before any DB checks)
# 2. Check postgres.json for required fields; if complete, call load_pg_env() and test reachability
# - Warns if PGPASSWORD is empty for a TCP host
# - If config is incomplete or DB unreachable, prompts for connection details
# - Exits immediately (non-zero) if stdin is not a TTY and config is needed
# 3. Check openclaw.json for API keys; prompts interactively if missing
# 4. exec agent-install.sh (which does all the real work: schema, hooks, scripts, skills)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$HOME/.openclaw"
PG_CONFIG="$CONFIG_DIR/postgres.json"
OPENCLAW_CONFIG="$CONFIG_DIR/openclaw.json"
# Color codes
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo "═══════════════════════════════════════════"
echo " nova-mind shell-install"
echo "═══════════════════════════════════════════"
echo ""
# ============================================
# Source libraries early (before any checks)
# ============================================
PG_ENV="$SCRIPT_DIR/lib/pg-env.sh"
if [ ! -f "$PG_ENV" ]; then
echo -e " ${RED}❌${NC} $PG_ENV not found"
exit 1
fi
source "$PG_ENV"
# Create config directory if needed
if [ ! -d "$CONFIG_DIR" ]; then
mkdir -p "$CONFIG_DIR"
chmod 700 "$CONFIG_DIR"
echo -e " ${GREEN}✅${NC} Created $CONFIG_DIR"
fi
# ============================================
# Part 1: Database config (postgres.json)
# ============================================
echo "Database configuration..."
# Check if postgres.json exists and has all required fields (field presence only — load_pg_env handles parsing)
_pg_config_complete() {
if [ ! -f "$PG_CONFIG" ]; then
return 1
fi
if ! command -v jq &>/dev/null; then
return 1
fi
for field in host port database user; do
local val
val=$(jq -r ".$field // empty" "$PG_CONFIG" 2>/dev/null)
if [ -z "$val" ]; then
return 1
fi
done
return 0
}
PG_COMPLETE=false
NEED_PROMPT=false
if _pg_config_complete; then
# Config file looks structurally complete — load env and test reachability
load_pg_env
echo " Resolved: PGHOST=$PGHOST PGDATABASE=${PGDATABASE:-(not set)} PGUSER=$PGUSER"
# Empty password warning for TCP hosts
if [[ "$PGHOST" != /* ]] && [ -z "${PGPASSWORD:-}" ]; then
echo -e " ${YELLOW}⚠️ PGPASSWORD is empty for a network host ($PGHOST)${NC}"
echo " The agent_chat plugin requires password auth for TCP connections."
echo " Consider adding a password to $PG_CONFIG"
fi
# Reachability check — PGPASSWORD is now exported by load_pg_env
if psql -c "SELECT 1" &>/dev/null; then
echo -e " ${GREEN}✅${NC} $PG_CONFIG exists and is complete"
PG_COMPLETE=true
else
echo -e " ${YELLOW}⚠️ $PG_CONFIG exists but database '$PGDATABASE' is not reachable${NC}"
echo " Reconfiguring database settings..."
NEED_PROMPT=true
fi
else
if [ ! -f "$PG_CONFIG" ]; then
: # No config file — will prompt
elif ! command -v jq &>/dev/null; then
echo -e " ${YELLOW}⚠️ jq not installed — cannot validate $PG_CONFIG${NC}"
else
# File exists but is missing fields
for field in host port database user; do
val=$(jq -r ".$field // empty" "$PG_CONFIG" 2>/dev/null)
if [ -z "$val" ]; then
echo -e " ${YELLOW}⚠️ $PG_CONFIG is missing '$field'${NC}"
fi
done
fi
NEED_PROMPT=true
fi
if [ "$NEED_PROMPT" = true ]; then
# Non-interactive guard — don't hang if no TTY
if ! [ -t 0 ]; then
echo -e " ${RED}❌${NC} Database configuration is required but stdin is not a TTY."
echo " Run this script interactively, or create $PG_CONFIG manually."
exit 1
fi
# Prompt for database connection details
DEFAULT_HOST="localhost"
DEFAULT_PORT="5432"
DEFAULT_USER="$(whoami)"
DEFAULT_DB="${DEFAULT_USER//-/_}_memory"
echo ""
echo " Enter PostgreSQL connection details (press Enter for defaults):"
echo ""
read -rp " Host [$DEFAULT_HOST]: " INPUT_HOST
read -rp " Port [$DEFAULT_PORT]: " INPUT_PORT
read -rp " Database [$DEFAULT_DB]: " INPUT_DB
read -rp " User [$DEFAULT_USER]: " INPUT_USER
read -rsp " Password []: " INPUT_PASS
echo ""
echo ""
# Prompt for postgres superuser credentials (session-only, NOT persisted)
DEFAULT_SUPERUSER="postgres"
DEFAULT_SUPERUSER_HOST="/var/run/postgresql"
echo " PostgreSQL superuser for schema operations (CREATE EXTENSION, DDL):"
read -rp " Superuser [$DEFAULT_SUPERUSER]: " INPUT_SUPERUSER
read -rsp " Superuser password []: " INPUT_SUPERUSER_PASS
echo ""
read -rp " Superuser host (unix socket path or hostname) [$DEFAULT_SUPERUSER_HOST]: " INPUT_SUPERUSER_HOST
echo ""
DB_HOST="${INPUT_HOST:-$DEFAULT_HOST}"
DB_PORT="${INPUT_PORT:-$DEFAULT_PORT}"
DB_NAME="${INPUT_DB:-$DEFAULT_DB}"
DB_USER="${INPUT_USER:-$DEFAULT_USER}"
DB_PASS="${INPUT_PASS:-}"
PG_SUPERUSER="${INPUT_SUPERUSER:-$DEFAULT_SUPERUSER}"
PG_SUPERUSER_PASSWORD="${INPUT_SUPERUSER_PASS:-}"
PG_SUPERUSER_HOST="${INPUT_SUPERUSER_HOST:-$DEFAULT_SUPERUSER_HOST}"
cat > "$PG_CONFIG" <<EOF
{
"host": "$DB_HOST",
"port": $DB_PORT,
"database": "$DB_NAME",
"user": "$DB_USER",
"password": "$DB_PASS"
}
EOF
chmod 600 "$PG_CONFIG"
echo -e " ${GREEN}✅${NC} Wrote $PG_CONFIG (chmod 600)"
# Reload env with the new config (this sets PGUSER/PGPASSWORD from the agent user)
load_pg_env
# Export superuser credentials for agent-install.sh (session-only)
export PG_SUPERUSER="$PG_SUPERUSER"
export PG_SUPERUSER_PASSWORD="$PG_SUPERUSER_PASSWORD"
export PG_SUPERUSER_HOST="$PG_SUPERUSER_HOST"
echo -e " ${GREEN}✅${NC} Superuser set to '$PG_SUPERUSER' (session-only, not persisted)"
echo -e " ${GREEN}✅${NC} Superuser host set to '$PG_SUPERUSER_HOST'"
echo " Resolved: PGHOST=$PGHOST PGDATABASE=${PGDATABASE:-(not set)} PGUSER=$PGUSER"
# Empty password warning for TCP hosts (post-prompt)
if [[ "$PGHOST" != /* ]] && [ -z "${PGPASSWORD:-}" ]; then
echo -e " ${YELLOW}⚠️ No password set for a network host ($PGHOST)${NC}"
echo " The agent_chat plugin requires password auth for TCP connections."
fi
fi
# ============================================
# Part 2: API keys (openclaw.json env.vars)
# ============================================
echo ""
echo "API key configuration..."
# Ensure openclaw.json exists
if [ ! -f "$OPENCLAW_CONFIG" ]; then
echo -e " ${YELLOW}⚠️ $OPENCLAW_CONFIG not found — creating minimal config${NC}"
echo '{}' > "$OPENCLAW_CONFIG"
fi
if ! command -v jq &>/dev/null; then
echo -e " ${RED}❌${NC} jq is required to manage openclaw.json"
echo " Install: sudo apt install jq"
exit 1
fi
# Check OPENAI_API_KEY
OPENAI_KEY=$(jq -r '.env.vars.OPENAI_API_KEY // empty' "$OPENCLAW_CONFIG" 2>/dev/null)
if [ -z "$OPENAI_KEY" ] && [ -z "${OPENAI_API_KEY:-}" ]; then
echo -e " ${YELLOW}⚠️ OPENAI_API_KEY not found${NC}"
echo " Required for semantic recall (embeddings)."
echo " Get a key from: https://platform.openai.com/api-keys"
echo ""
if ! [ -t 0 ]; then
echo -e " ${YELLOW}⚠️ Non-interactive mode — skipping OPENAI_API_KEY prompt${NC}"
else
read -rp " Enter your OpenAI API key (or press Enter to skip): " INPUT_OPENAI_KEY
if [ -n "$INPUT_OPENAI_KEY" ]; then
# Write to openclaw.json env.vars
TMP_CONFIG=$(mktemp)
jq --arg key "$INPUT_OPENAI_KEY" '.env.vars.OPENAI_API_KEY = $key' "$OPENCLAW_CONFIG" > "$TMP_CONFIG"
mv "$TMP_CONFIG" "$OPENCLAW_CONFIG"
export OPENAI_API_KEY="$INPUT_OPENAI_KEY"
echo -e " ${GREEN}✅${NC} OPENAI_API_KEY written to $OPENCLAW_CONFIG"
else
echo -e " ${YELLOW}⚠️ Skipped — semantic recall will not work without OPENAI_API_KEY${NC}"
fi
fi
elif [ -n "$OPENAI_KEY" ]; then
export OPENAI_API_KEY="$OPENAI_KEY"
echo -e " ${GREEN}✅${NC} OPENAI_API_KEY found in $OPENCLAW_CONFIG"
else
echo -e " ${GREEN}✅${NC} OPENAI_API_KEY set in environment"
fi
# Check ANTHROPIC_API_KEY
ANTHROPIC_KEY=$(jq -r '.env.vars.ANTHROPIC_API_KEY // empty' "$OPENCLAW_CONFIG" 2>/dev/null)
if [ -z "$ANTHROPIC_KEY" ] && [ -z "${ANTHROPIC_API_KEY:-}" ]; then
echo -e " ${YELLOW}⚠️ ANTHROPIC_API_KEY not found${NC}"
echo " Used by OpenClaw as the primary LLM provider."
echo " Get a key from: https://console.anthropic.com/settings/keys"
echo ""
if ! [ -t 0 ]; then
echo -e " ${YELLOW}⚠️ Non-interactive mode — skipping ANTHROPIC_API_KEY prompt${NC}"
else
read -rp " Enter your Anthropic API key (or press Enter to skip): " INPUT_ANTHROPIC_KEY
if [ -n "$INPUT_ANTHROPIC_KEY" ]; then
# Write to openclaw.json env.vars
TMP_CONFIG=$(mktemp)
jq --arg key "$INPUT_ANTHROPIC_KEY" '.env.vars.ANTHROPIC_API_KEY = $key' "$OPENCLAW_CONFIG" > "$TMP_CONFIG"
mv "$TMP_CONFIG" "$OPENCLAW_CONFIG"
export ANTHROPIC_API_KEY="$INPUT_ANTHROPIC_KEY"
echo -e " ${GREEN}✅${NC} ANTHROPIC_API_KEY written to $OPENCLAW_CONFIG"
else
echo -e " ${YELLOW}⚠️ Skipped — some hooks and LLM features may not work without ANTHROPIC_API_KEY${NC}"
fi
fi
elif [ -n "$ANTHROPIC_KEY" ]; then
export ANTHROPIC_API_KEY="$ANTHROPIC_KEY"
echo -e " ${GREEN}✅${NC} ANTHROPIC_API_KEY found in $OPENCLAW_CONFIG"
else
echo -e " ${GREEN}✅${NC} ANTHROPIC_API_KEY set in environment"
fi
# ============================================
# Part 3: Hand off to agent-install.sh
# ============================================
echo ""
echo "Config setup complete. Running agent-install.sh..."
echo ""
exec "$SCRIPT_DIR/agent-install.sh" "$@"