somratpro Claude Haiku 4.5 commited on
Commit
a2c720b
Β·
1 Parent(s): dcedf5f

fix: bootstrap-ceo after Paperclip init, better startup error messages

Browse files

- Start Paperclip in background, wait for config.json + /api/health (max 90s)
- Run bootstrap-ceo after server is ready (config exists), not before
- Print boxed admin invite URL to logs when bootstrap generates one
- Proxy shows "starting up" message instead of generic error during boot
- Cleanup handler now kills PAPERCLIP_PID on SIGTERM

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

Files changed (2) hide show
  1. health-server.js +2 -1
  2. start.sh +38 -13
health-server.js CHANGED
@@ -197,8 +197,9 @@ app.all("*", async (req, res) => {
197
 
198
  res.status(response.statusCode).send(response.body);
199
  } catch (error) {
 
200
  res.status(503).json({
201
- error: "Paperclip service unavailable",
202
  details: error.message,
203
  });
204
  }
 
197
 
198
  res.status(response.statusCode).send(response.body);
199
  } catch (error) {
200
+ const starting = error.message && error.message.includes("ECONNREFUSED");
201
  res.status(503).json({
202
+ error: starting ? "Paperclip starting up, please wait..." : "Paperclip service unavailable",
203
  details: error.message,
204
  });
205
  }
start.sh CHANGED
@@ -243,6 +243,7 @@ cleanup() {
243
  echo "Stopping services..."
244
  [ -n "$HEALTH_PID" ] && kill $HEALTH_PID 2>/dev/null || true
245
  [ -n "$SYNC_PID" ] && kill $SYNC_PID 2>/dev/null || true
 
246
 
247
  echo -e "${GREEN}Shutdown complete${NC}"
248
  exit 0
@@ -250,19 +251,43 @@ cleanup() {
250
 
251
  trap cleanup SIGTERM SIGINT
252
 
253
- # Generate first admin invite URL if no admin exists yet
254
- # Runs against the database directly (no server needed) and prints the URL to logs
255
- echo -e "${BLUE}[8/8] Bootstrapping admin account...${NC}"
256
- BOOTSTRAP_OUTPUT=$(pnpm paperclipai auth bootstrap-ceo 2>&1)
257
- if echo "$BOOTSTRAP_OUTPUT" | grep -qi "invite\|http\|url\|link"; then
258
- echo -e "${GREEN}βœ“ Admin invite URL:${NC}"
259
- echo "$BOOTSTRAP_OUTPUT"
260
- echo -e "${YELLOW}Copy the URL above to complete first-time setup.${NC}\n"
261
- elif echo "$BOOTSTRAP_OUTPUT" | grep -qi "already\|exists\|skip"; then
262
- echo -e "${GREEN}βœ“ Admin account already exists${NC}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  else
264
- echo -e "${YELLOW}Bootstrap output: ${BOOTSTRAP_OUTPUT}${NC}\n"
265
  fi
266
 
267
- # Start Paperclip server with tsx loader (loads workspace .ts packages at runtime)
268
- exec node --import ./server/node_modules/tsx/dist/loader.mjs server/dist/index.js
 
243
  echo "Stopping services..."
244
  [ -n "$HEALTH_PID" ] && kill $HEALTH_PID 2>/dev/null || true
245
  [ -n "$SYNC_PID" ] && kill $SYNC_PID 2>/dev/null || true
246
+ [ -n "$PAPERCLIP_PID" ] && kill $PAPERCLIP_PID 2>/dev/null || true
247
 
248
  echo -e "${GREEN}Shutdown complete${NC}"
249
  exit 0
 
251
 
252
  trap cleanup SIGTERM SIGINT
253
 
254
+ # ============================================================================
255
+ # 8. Start Paperclip, wait for init, then bootstrap admin
256
+ # ============================================================================
257
+ echo -e "${BLUE}[8/8] Starting Paperclip server...${NC}"
258
+
259
+ # Start Paperclip in background so we can run post-init steps
260
+ node --import ./server/node_modules/tsx/dist/loader.mjs server/dist/index.js &
261
+ PAPERCLIP_PID=$!
262
+
263
+ # Wait for Paperclip to create config.json and health endpoint to respond (max 90s)
264
+ CONFIG_FILE="/paperclip/instances/default/config.json"
265
+ echo "Waiting for Paperclip to initialize..."
266
+ for i in $(seq 1 45); do
267
+ if [ -f "$CONFIG_FILE" ] && curl -sf http://localhost:3100/api/health >/dev/null 2>&1; then
268
+ echo -e "${GREEN}βœ“ Paperclip ready (${i}s)${NC}"
269
+ break
270
+ fi
271
+ sleep 2
272
+ done
273
+
274
+ # Bootstrap first admin β€” generates invite URL (only works if no admin exists)
275
+ if [ -f "$CONFIG_FILE" ]; then
276
+ echo -e "${BLUE}Bootstrapping admin account...${NC}"
277
+ BOOTSTRAP_OUTPUT=$(pnpm paperclipai auth bootstrap-ceo 2>&1 || true)
278
+ if echo "$BOOTSTRAP_OUTPUT" | grep -q "http"; then
279
+ INVITE_URL=$(echo "$BOOTSTRAP_OUTPUT" | grep -o 'https\?://[^ ]*' | head -1)
280
+ echo -e "${GREEN}╔══════════════════════════════════════════════╗${NC}"
281
+ echo -e "${GREEN}β•‘ ADMIN SETUP URL (open in browser): β•‘${NC}"
282
+ echo -e "${GREEN}β•‘ ${INVITE_URL}${NC}"
283
+ echo -e "${GREEN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}"
284
+ else
285
+ # Already configured or no output β€” not an error
286
+ echo -e "${GREEN}βœ“ Admin account ready${NC}"
287
+ fi
288
  else
289
+ echo -e "${YELLOW}Warning: Paperclip config not found, skipping admin bootstrap${NC}"
290
  fi
291
 
292
+ # Keep container alive β€” wait for Paperclip process to exit
293
+ wait $PAPERCLIP_PID