Files
maskanx_cm_backend/deploy/entrypoint.sh
T
AFFAANhandClaude Opus 5 19e1e84fb7 Initial commit: MaskanX backend
Independent FastAPI backend for the MaskanX agentic growth platform.

Includes the agent runtime, MCP client integrations (Meta Ads, LinkedIn,
HubSpot, Tavily, Exa, xAI, Citedy, image generation), PostgreSQL storage
for chats and cron jobs, provider and secret management, and the CLI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 10:28:22 +05:30

154 lines
6.0 KiB
Bash

#!/bin/sh
# Substitute the app port in supervisord template and start supervisord.
# Default port 8088; override at runtime with -e MASKANX_PORT=3000.
set -e
export ADCLAW_PORT="${MASKANX_PORT:-${ADCLAW_PORT:-8088}}"
export ADCLAW_WORKING_DIR="${MASKANX_WORKING_DIR:-${ADCLAW_WORKING_DIR:-/app/working}}"
export ADCLAW_SECRET_DIR="${MASKANX_SECRET_DIR:-${ADCLAW_SECRET_DIR:-/app/working.secret}}"
export ADCLAW_ENABLED_CHANNELS="${MASKANX_ENABLED_CHANNELS:-${ADCLAW_ENABLED_CHANNELS:-discord,dingtalk,feishu,qq,console,telegram}}"
export ADCLAW_STORAGE_BACKEND="${MASKANX_STORAGE_BACKEND:-${ADCLAW_STORAGE_BACKEND:-json}}"
# Ensure config.json exists (first run only — don't overwrite user config)
CONFIG="${ADCLAW_WORKING_DIR}/config.json"
if [ ! -f "$CONFIG" ] || [ ! -s "$CONFIG" ]; then
echo "entrypoint: No config.json found, generating default..."
maskanx init --defaults --accept-security 2>/dev/null || true
fi
# Migrate config.json — apply new defaults to existing config without overwriting user data
python3 -c "
import json, os, sys
cfg_path = os.environ.get('ADCLAW_WORKING_DIR', '/app/working') + '/config.json'
if not os.path.isfile(cfg_path):
sys.exit(0)
with open(cfg_path) as f:
cfg = json.load(f)
changed = False
# Force correct defaults that should never be True in production
if cfg.get('show_tool_details') is not False:
cfg['show_tool_details'] = False
changed = True
# Ensure filter_tool_messages=True on all channels
for ch_name, ch_cfg in cfg.get('channels', {}).items():
if isinstance(ch_cfg, dict) and ch_cfg.get('filter_tool_messages') is not True:
ch_cfg['filter_tool_messages'] = True
changed = True
if changed:
with open(cfg_path, 'w') as f:
json.dump(cfg, f, indent=2, ensure_ascii=False)
print('entrypoint: config.json migrated (applied new defaults)')
else:
print('entrypoint: config.json OK (no migration needed)')
" 2>/dev/null || true
# Enable Citedy MCP client if API key is provided at runtime
if [ -n "$CITEDY_API_KEY" ]; then
CONFIG="${ADCLAW_WORKING_DIR}/config.json"
if [ -f "$CONFIG" ]; then
python3 -c "
import json, os
cfg_path = os.environ.get('ADCLAW_WORKING_DIR', '/app/working') + '/config.json'
with open(cfg_path) as f:
cfg = json.load(f)
mcp = cfg.setdefault('mcp', {}).setdefault('clients', {})
key = os.environ['CITEDY_API_KEY']
mcp['citedy'] = {
'name': 'citedy_mcp',
'description': 'Citedy SEO & Marketing Tools (70+ tools)',
'enabled': True,
'transport': 'streamable_http',
'url': 'https://mcp.citedy.com/mcp',
'headers': {'Authorization': f'Bearer {key}', 'Accept': 'application/json, text/event-stream'},
'env': {'CITEDY_API_KEY': key},
}
with open(cfg_path, 'w') as f:
json.dump(cfg, f, indent=2)
print('entrypoint: Citedy MCP client enabled')
" 2>/dev/null || true
fi
fi
# Enable Exa search MCP if API key is provided at runtime
if [ -n "$EXA_API_KEY" ]; then
CONFIG="${ADCLAW_WORKING_DIR}/config.json"
if [ -f "$CONFIG" ]; then
python3 -c "
import json, os
cfg_path = os.environ.get('ADCLAW_WORKING_DIR', '/app/working') + '/config.json'
with open(cfg_path) as f:
cfg = json.load(f)
mcp = cfg.setdefault('mcp', {}).setdefault('clients', {})
key = os.environ['EXA_API_KEY']
mcp['exa'] = {
'name': 'exa_mcp',
'description': 'Exa AI search: web, code, people, companies',
'enabled': True,
'command': 'npx',
'args': ['-y', 'exa-mcp-server'],
'env': {'EXA_API_KEY': key},
}
with open(cfg_path, 'w') as f:
json.dump(cfg, f, indent=2)
print('entrypoint: Exa MCP client enabled')
" 2>/dev/null || true
fi
fi
# Enable Telegram channel if bot token is provided at runtime
if [ -n "$TELEGRAM_BOT_TOKEN" ]; then
CONFIG="${ADCLAW_WORKING_DIR}/config.json"
if [ -f "$CONFIG" ]; then
python3 -c "
import json, os
cfg_path = os.environ.get('ADCLAW_WORKING_DIR', '/app/working') + '/config.json'
with open(cfg_path) as f:
cfg = json.load(f)
tg = cfg.setdefault('channels', {}).setdefault('telegram', {})
tg['enabled'] = True
tg['bot_token'] = os.environ['TELEGRAM_BOT_TOKEN']
with open(cfg_path, 'w') as f:
json.dump(cfg, f, indent=2)
print('entrypoint: Telegram channel enabled')
" 2>/dev/null || true
fi
fi
# Sync new built-in skills to active_skills (non-destructive: skip existing)
python3 -c "
from adclaw.agents.skills_manager import sync_skills_to_working_dir
synced, skipped = sync_skills_to_working_dir(skill_names=None, force=False)
if synced:
print(f'entrypoint: synced {synced} new skill(s) to active_skills')
else:
print(f'entrypoint: all skills up to date ({skipped} existing)')
" 2>/dev/null || true
# Ensure working dirs are owned by MaskanX user (entrypoint runs as root)
mkdir -p /app/logs 2>/dev/null || true
chown -R maskanx:maskanx "${ADCLAW_WORKING_DIR}" "${ADCLAW_SECRET_DIR}" /app/logs 2>/dev/null || true
# Run Postgres migrations when requested. Keep JSON/file mode as the default so
# local users can still start the app without a database.
case "$(printf '%s' "$ADCLAW_STORAGE_BACKEND" | tr '[:upper:]' '[:lower:]')" in
postgres|postgresql|pg)
echo "entrypoint: PostgreSQL storage enabled, running migrations..."
maskanx db migrate
;;
esac
# Generate supervisord.conf from templates based on MASKANX_VARIANT.
# core → base template only (supervisord + app).
# browser/full → base + browser template (adds dbus, xvfb, xfce4, pinchtab).
MASKANX_VARIANT="${MASKANX_VARIANT:-${ADCLAW_VARIANT:-full}}"
SUPERVISORD_CONF="/etc/supervisor/conf.d/supervisord.conf"
envsubst '${ADCLAW_PORT}' \
< /etc/supervisor/conf.d/supervisord.conf.template \
> "$SUPERVISORD_CONF"
if [ "$MASKANX_VARIANT" != "core" ] && [ -f /etc/supervisor/conf.d/supervisord.browser.conf.template ]; then
cat /etc/supervisor/conf.d/supervisord.browser.conf.template >> "$SUPERVISORD_CONF"
echo "entrypoint: supervisord configured with browser programs (variant=${MASKANX_VARIANT})"
else
echo "entrypoint: supervisord configured without browser (variant=${MASKANX_VARIANT})"
fi
exec /usr/bin/supervisord -c "$SUPERVISORD_CONF"