Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- .pytest_cache/v/cache/nodeids +2 -0
- Dockerfile +6 -0
- deploy/nginx.conf +28 -0
- deploy/supervisord.conf +50 -0
- entrypoint.sh +106 -13
.pytest_cache/v/cache/nodeids
CHANGED
|
@@ -4,6 +4,8 @@
|
|
| 4 |
"tests/test_agent_api.py::test_agent_operations_use_canonical_workspace_scope",
|
| 5 |
"tests/test_agent_api.py::test_agent_security_discovery_and_openapi",
|
| 6 |
"tests/test_agent_api.py::test_relationship_worker_rejects_missing_brain_scope",
|
|
|
|
|
|
|
| 7 |
"tests/test_deploy_production_contract.py::test_backup_manifest_verification_detects_tampering",
|
| 8 |
"tests/test_deploy_production_contract.py::test_ci_embedding_stub_is_deterministic_and_normalized",
|
| 9 |
"tests/test_deploy_production_contract.py::test_ci_profiles_enable_dense_search_without_online_llm",
|
|
|
|
| 4 |
"tests/test_agent_api.py::test_agent_operations_use_canonical_workspace_scope",
|
| 5 |
"tests/test_agent_api.py::test_agent_security_discovery_and_openapi",
|
| 6 |
"tests/test_agent_api.py::test_relationship_worker_rejects_missing_brain_scope",
|
| 7 |
+
"tests/test_config_backend_selection.py::test_config_default_backends",
|
| 8 |
+
"tests/test_config_backend_selection.py::test_config_postgres_profile",
|
| 9 |
"tests/test_deploy_production_contract.py::test_backup_manifest_verification_detects_tampering",
|
| 10 |
"tests/test_deploy_production_contract.py::test_ci_embedding_stub_is_deterministic_and_normalized",
|
| 11 |
"tests/test_deploy_production_contract.py::test_ci_profiles_enable_dense_search_without_online_llm",
|
Dockerfile
CHANGED
|
@@ -79,6 +79,12 @@ RUN apt-get update && apt-get upgrade -y \
|
|
| 79 |
&& apt-get install -y --no-install-recommends \
|
| 80 |
curl \
|
| 81 |
util-linux \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
&& rm -rf /var/lib/apt/lists/* \
|
| 83 |
&& python -m pip uninstall -y setuptools wheel \
|
| 84 |
&& groupadd -r appuser && useradd -r -g appuser -m appuser
|
|
|
|
| 79 |
&& apt-get install -y --no-install-recommends \
|
| 80 |
curl \
|
| 81 |
util-linux \
|
| 82 |
+
postgresql \
|
| 83 |
+
postgresql-contrib \
|
| 84 |
+
postgresql-15-pgvector \
|
| 85 |
+
redis-server \
|
| 86 |
+
nginx \
|
| 87 |
+
supervisor \
|
| 88 |
&& rm -rf /var/lib/apt/lists/* \
|
| 89 |
&& python -m pip uninstall -y setuptools wheel \
|
| 90 |
&& groupadd -r appuser && useradd -r -g appuser -m appuser
|
deploy/nginx.conf
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
server {
|
| 2 |
+
listen 7860;
|
| 3 |
+
server_name _;
|
| 4 |
+
|
| 5 |
+
client_max_body_size 100M;
|
| 6 |
+
|
| 7 |
+
location ~ ^/brains/[^/]+/mcp(/.*)?$ {
|
| 8 |
+
proxy_pass http://127.0.0.1:8001;
|
| 9 |
+
proxy_http_version 1.1;
|
| 10 |
+
proxy_set_header Host $host;
|
| 11 |
+
proxy_set_header X-Real-IP $remote_addr;
|
| 12 |
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
| 13 |
+
proxy_set_header X-Forwarded-Proto $scheme;
|
| 14 |
+
proxy_set_header Connection "";
|
| 15 |
+
proxy_buffering off;
|
| 16 |
+
proxy_cache off;
|
| 17 |
+
chunked_transfer_encoding off;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
location / {
|
| 21 |
+
proxy_pass http://127.0.0.1:8000;
|
| 22 |
+
proxy_http_version 1.1;
|
| 23 |
+
proxy_set_header Host $host;
|
| 24 |
+
proxy_set_header X-Real-IP $remote_addr;
|
| 25 |
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
| 26 |
+
proxy_set_header X-Forwarded-Proto $scheme;
|
| 27 |
+
}
|
| 28 |
+
}
|
deploy/supervisord.conf
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[supervisord]
|
| 2 |
+
nodaemon=true
|
| 3 |
+
user=root
|
| 4 |
+
logfile=/var/log/supervisord.log
|
| 5 |
+
pidfile=/var/run/supervisord.pid
|
| 6 |
+
|
| 7 |
+
[program:postgres]
|
| 8 |
+
command=su - postgres -c "/usr/lib/postgresql/15/bin/postgres -D %(env(PGDATA)s) -c config_file=%(env(PGDATA)s)/postgresql.conf"
|
| 9 |
+
autostart=true
|
| 10 |
+
autorestart=true
|
| 11 |
+
stdout_logfile=/var/log/postgres.log
|
| 12 |
+
stderr_logfile=/var/log/postgres.err
|
| 13 |
+
|
| 14 |
+
[program:redis]
|
| 15 |
+
command=redis-server /etc/redis/redis.conf
|
| 16 |
+
autostart=true
|
| 17 |
+
autorestart=true
|
| 18 |
+
stdout_logfile=/var/log/redis.log
|
| 19 |
+
stderr_logfile=/var/log/redis.err
|
| 20 |
+
|
| 21 |
+
[program:brainapi-api]
|
| 22 |
+
command=/app/.venv/bin/python -m uvicorn src.services.api.app:app --host 127.0.0.1 --port 8000
|
| 23 |
+
directory=/app
|
| 24 |
+
autostart=true
|
| 25 |
+
autorestart=true
|
| 26 |
+
stdout_logfile=/var/log/brainapi-api.log
|
| 27 |
+
stderr_logfile=/var/log/brainapi-api.err
|
| 28 |
+
|
| 29 |
+
[program:brainapi-mcp]
|
| 30 |
+
command=/app/.venv/bin/python -m src.services.mcp.main
|
| 31 |
+
directory=/app
|
| 32 |
+
autostart=true
|
| 33 |
+
autorestart=true
|
| 34 |
+
stdout_logfile=/var/log/brainapi-mcp.log
|
| 35 |
+
stderr_logfile=/var/log/brainapi-mcp.err
|
| 36 |
+
|
| 37 |
+
[program:brainapi-worker]
|
| 38 |
+
command=/app/.venv/bin/python -m celery -A src.services.tasks.main.celery_app worker --loglevel=info
|
| 39 |
+
directory=/app
|
| 40 |
+
autostart=true
|
| 41 |
+
autorestart=true
|
| 42 |
+
stdout_logfile=/var/log/brainapi-worker.log
|
| 43 |
+
stderr_logfile=/var/log/brainapi-worker.err
|
| 44 |
+
|
| 45 |
+
[program:nginx]
|
| 46 |
+
command=nginx -g "daemon off;"
|
| 47 |
+
autostart=true
|
| 48 |
+
autorestart=true
|
| 49 |
+
stdout_logfile=/var/log/nginx.log
|
| 50 |
+
stderr_logfile=/var/log/nginx.err
|
entrypoint.sh
CHANGED
|
@@ -1,6 +1,100 @@
|
|
| 1 |
#!/bin/bash
|
| 2 |
set -e
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
plugin_failure_policy="${PLUGIN_FAILURE_POLICY:-}"
|
| 5 |
if [ -z "$plugin_failure_policy" ]; then
|
| 6 |
if [ "${ENV:-production}" = "development" ]; then
|
|
@@ -9,17 +103,8 @@ if [ -z "$plugin_failure_policy" ]; then
|
|
| 9 |
plugin_failure_policy="fail"
|
| 10 |
fi
|
| 11 |
fi
|
| 12 |
-
if [ "$plugin_failure_policy" != "fail" ] && [ "$plugin_failure_policy" != "warn" ]; then
|
| 13 |
-
echo "[brainapi] PLUGIN_FAILURE_POLICY must be 'fail' or 'warn'" >&2
|
| 14 |
-
exit 64
|
| 15 |
-
fi
|
| 16 |
-
|
| 17 |
-
if [ -d /app/.cache ]; then
|
| 18 |
-
chown -R appuser:appuser /app/.cache 2>/dev/null || true
|
| 19 |
-
fi
|
| 20 |
|
| 21 |
mkdir -p /app/plugins
|
| 22 |
-
chown -R appuser:appuser /app/plugins 2>/dev/null || true
|
| 23 |
|
| 24 |
if [ -n "$BRAINAPI_PLUGINS" ]; then
|
| 25 |
IFS=',' read -ra PLUGINS <<< "$BRAINAPI_PLUGINS"
|
|
@@ -29,8 +114,7 @@ if [ -n "$BRAINAPI_PLUGINS" ]; then
|
|
| 29 |
version="${plugin_spec##*:}"
|
| 30 |
[ "$name" = "$version" ] && version="latest"
|
| 31 |
echo "[brainapi] Installing plugin: $name v$version"
|
| 32 |
-
if !
|
| 33 |
-
/app/.venv/bin/python -m src.core.plugins.cli plugins install "$name" --version "$version"; then
|
| 34 |
if [ "$plugin_failure_policy" = "fail" ]; then
|
| 35 |
echo "[brainapi] Failed to install required plugin '$name'" >&2
|
| 36 |
exit 1
|
|
@@ -40,5 +124,14 @@ if [ -n "$BRAINAPI_PLUGINS" ]; then
|
|
| 40 |
done
|
| 41 |
fi
|
| 42 |
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
#!/bin/bash
|
| 2 |
set -e
|
| 3 |
|
| 4 |
+
# 1. Hugging Face Space runtime environment configuration
|
| 5 |
+
export DATA_DB="${DATA_DB:-postgresql}"
|
| 6 |
+
export VECTOR_DB="${VECTOR_DB:-postgresql}"
|
| 7 |
+
export GRAPH_DB="${GRAPH_DB:-networkx}"
|
| 8 |
+
export CELERY_BACKEND="${CELERY_BACKEND:-redis}"
|
| 9 |
+
|
| 10 |
+
export POSTGRES_HOST="${POSTGRES_HOST:-127.0.0.1}"
|
| 11 |
+
export POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
| 12 |
+
export POSTGRES_USERNAME="${POSTGRES_USERNAME:-brainapi}"
|
| 13 |
+
export POSTGRES_SYSTEM_DATABASE="${POSTGRES_SYSTEM_DATABASE:-brainapi}"
|
| 14 |
+
export POSTGRES_MAINTENANCE_DATABASE="${POSTGRES_MAINTENANCE_DATABASE:-postgres}"
|
| 15 |
+
|
| 16 |
+
export REDIS_HOST="${REDIS_HOST:-127.0.0.1}"
|
| 17 |
+
export REDIS_PORT="${REDIS_PORT:-6379}"
|
| 18 |
+
|
| 19 |
+
export DEFAULT_BRAIN_FALLBACK="${DEFAULT_BRAIN_FALLBACK:-false}"
|
| 20 |
+
export MCP_PORT="${MCP_PORT:-8001}"
|
| 21 |
+
|
| 22 |
+
# Persistent root determination
|
| 23 |
+
if [ -d "/data" ]; then
|
| 24 |
+
PERSISTENT_ROOT="/data/brainapi"
|
| 25 |
+
else
|
| 26 |
+
PERSISTENT_ROOT="/app/.data/brainapi"
|
| 27 |
+
fi
|
| 28 |
+
|
| 29 |
+
mkdir -p "$PERSISTENT_ROOT/postgres" "$PERSISTENT_ROOT/redis"
|
| 30 |
+
chmod 700 "$PERSISTENT_ROOT"
|
| 31 |
+
|
| 32 |
+
SECRETS_FILE="$PERSISTENT_ROOT/internal-secrets.env"
|
| 33 |
+
if [ ! -f "$SECRETS_FILE" ]; then
|
| 34 |
+
PG_PASS="$(openssl rand -hex 16 2>/dev/null || date +%s%N | sha256sum | head -c 32)"
|
| 35 |
+
RED_PASS="$(openssl rand -hex 16 2>/dev/null || date +%s%N | sha256sum | head -c 32)"
|
| 36 |
+
cat <<EOF > "$SECRETS_FILE"
|
| 37 |
+
POSTGRES_PASSWORD=$PG_PASS
|
| 38 |
+
REDIS_PASSWORD=$RED_PASS
|
| 39 |
+
EOF
|
| 40 |
+
chmod 0600 "$SECRETS_FILE"
|
| 41 |
+
fi
|
| 42 |
+
|
| 43 |
+
source "$SECRETS_FILE"
|
| 44 |
+
export POSTGRES_PASSWORD
|
| 45 |
+
export REDIS_PASSWORD
|
| 46 |
+
|
| 47 |
+
# Print non-secret startup diagnostics
|
| 48 |
+
echo "=================================================="
|
| 49 |
+
echo "Starting BrainAPI Hugging Face Space Runtime"
|
| 50 |
+
echo "DATA_DB=$DATA_DB"
|
| 51 |
+
echo "VECTOR_DB=$VECTOR_DB"
|
| 52 |
+
echo "GRAPH_DB=$GRAPH_DB"
|
| 53 |
+
echo "POSTGRES_HOST=$POSTGRES_HOST"
|
| 54 |
+
echo "REDIS_HOST=$REDIS_HOST"
|
| 55 |
+
echo "persistent_root=$PERSISTENT_ROOT"
|
| 56 |
+
echo "=================================================="
|
| 57 |
+
|
| 58 |
+
# 2. PostgreSQL Setup
|
| 59 |
+
PGDATA="$PERSISTENT_ROOT/postgres"
|
| 60 |
+
export PGDATA
|
| 61 |
+
chown -R postgres:postgres "$PGDATA"
|
| 62 |
+
|
| 63 |
+
if [ ! -s "$PGDATA/PG_VERSION" ]; then
|
| 64 |
+
su - postgres -c "/usr/lib/postgresql/15/bin/initdb -D '$PGDATA'"
|
| 65 |
+
echo "listen_addresses = '127.0.0.1'" >> "$PGDATA/postgresql.conf"
|
| 66 |
+
fi
|
| 67 |
+
|
| 68 |
+
# Temporary start Postgres for role/db initialization
|
| 69 |
+
su - postgres -c "/usr/lib/postgresql/15/bin/pg_ctl -D '$PGDATA' -w start"
|
| 70 |
+
|
| 71 |
+
# Create maintenance db, system db, role, and extension
|
| 72 |
+
su - postgres -c "psql -c \"CREATE USER $POSTGRES_USERNAME WITH PASSWORD '$POSTGRES_PASSWORD';\" 2>/dev/null || true"
|
| 73 |
+
su - postgres -c "psql -c \"ALTER USER $POSTGRES_USERNAME WITH PASSWORD '$POSTGRES_PASSWORD';\" 2>/dev/null || true"
|
| 74 |
+
su - postgres -c "psql -c \"CREATE DATABASE $POSTGRES_SYSTEM_DATABASE OWNER $POSTGRES_USERNAME;\" 2>/dev/null || true"
|
| 75 |
+
su - postgres -c "psql -d $POSTGRES_SYSTEM_DATABASE -c 'CREATE EXTENSION IF NOT EXISTS vector;' 2>/dev/null || true"
|
| 76 |
+
su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_SYSTEM_DATABASE TO $POSTGRES_USERNAME;\" 2>/dev/null || true"
|
| 77 |
+
su - postgres -c "psql -c \"ALTER USER $POSTGRES_USERNAME CREATEDB;\" 2>/dev/null || true"
|
| 78 |
+
|
| 79 |
+
su - postgres -c "/usr/lib/postgresql/15/bin/pg_ctl -D '$PGDATA' -w stop"
|
| 80 |
+
|
| 81 |
+
# 3. Redis Setup
|
| 82 |
+
cat <<EOF > /etc/redis/redis.conf
|
| 83 |
+
bind 127.0.0.1
|
| 84 |
+
port $REDIS_PORT
|
| 85 |
+
requirepass $REDIS_PASSWORD
|
| 86 |
+
dir $PERSISTENT_ROOT/redis
|
| 87 |
+
appendonly yes
|
| 88 |
+
appendfilename "appendonly.aof"
|
| 89 |
+
EOF
|
| 90 |
+
|
| 91 |
+
# 4. Nginx Setup
|
| 92 |
+
if [ -f /app/deploy/nginx.conf ]; then
|
| 93 |
+
cp /app/deploy/nginx.conf /etc/nginx/conf.d/default.conf
|
| 94 |
+
rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
|
| 95 |
+
fi
|
| 96 |
+
|
| 97 |
+
# 5. Plugin setup
|
| 98 |
plugin_failure_policy="${PLUGIN_FAILURE_POLICY:-}"
|
| 99 |
if [ -z "$plugin_failure_policy" ]; then
|
| 100 |
if [ "${ENV:-production}" = "development" ]; then
|
|
|
|
| 103 |
plugin_failure_policy="fail"
|
| 104 |
fi
|
| 105 |
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
mkdir -p /app/plugins
|
|
|
|
| 108 |
|
| 109 |
if [ -n "$BRAINAPI_PLUGINS" ]; then
|
| 110 |
IFS=',' read -ra PLUGINS <<< "$BRAINAPI_PLUGINS"
|
|
|
|
| 114 |
version="${plugin_spec##*:}"
|
| 115 |
[ "$name" = "$version" ] && version="latest"
|
| 116 |
echo "[brainapi] Installing plugin: $name v$version"
|
| 117 |
+
if ! /app/.venv/bin/python -m src.core.plugins.cli plugins install "$name" --version "$version"; then
|
|
|
|
| 118 |
if [ "$plugin_failure_policy" = "fail" ]; then
|
| 119 |
echo "[brainapi] Failed to install required plugin '$name'" >&2
|
| 120 |
exit 1
|
|
|
|
| 124 |
done
|
| 125 |
fi
|
| 126 |
|
| 127 |
+
# Copy supervisor config if present
|
| 128 |
+
if [ -f /app/deploy/supervisord.conf ]; then
|
| 129 |
+
cp /app/deploy/supervisord.conf /etc/supervisor/supervisord.conf
|
| 130 |
+
fi
|
| 131 |
+
|
| 132 |
+
# Execute supervisor or passed command
|
| 133 |
+
if [ "$1" = "supervisord" ] || [ -z "$1" ]; then
|
| 134 |
+
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
| 135 |
+
else
|
| 136 |
+
exec "$@"
|
| 137 |
+
fi
|