Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .gitlab/ci/container-boot.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,38 @@ container:boot:sculptor:
- docker ps --all
- docker compose logs sculptor -f &
- docker compose run curl-sculptor

container:boot:velorum:
extends:
- .container:boot
needs:
- generate-environment
- manifest:velorum
script:
- bundle install
- docker compose up velorum -d
- docker compose logs velorum -f &
- support/grpc_check_health --host docker:50052 --service liveness --retries 20
- support/grpc_check_health --host docker:50052 --service readiness --retries 20

container:boot:velorum:offline:
extends:
- .container:boot
needs:
- generate-environment
- manifest:velorum
script:
- docker compose up velorum-offline -d
- docker compose logs velorum-offline -f &
- |
for i in $(seq 1 30); do
STATUS=$(docker inspect --format='{{.State.Health.Status}}' $(docker compose ps -q velorum-offline) 2>/dev/null || echo "starting")
echo "Attempt $i/30: $STATUS"
if [ "$STATUS" = "healthy" ]; then
echo "Velorum booted successfully without network access"
exit 0
fi
sleep 1
done
echo "Timed out waiting for healthy status"
exit 1
15 changes: 15 additions & 0 deletions .gitlab/ci/container-build.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,18 @@ manifest:sculptor:
PLATFORM:
- amd64
- arm64

container:velorum:
extends:
- .single-image-build-base
needs:
- generate-environment
variables:
NEED_PROJECT_DOWNLOAD: 'true'

manifest:velorum:
extends:
- .manifest-create-base
needs:
- generate-environment
- container:velorum
15 changes: 15 additions & 0 deletions container/config-generator/generate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ def env?(key)
def env_set?(key)
@env.fetch(key, nil) != nil
end

def find_envs(pattern, group: false)
if group
@env.each_with_object({}) do |(key, value), groups|
match = key.match(pattern)
next unless match

group_key = match[1]
suffix = key.sub(/.*#{Regexp.escape(group_key)}_?/, '')
(groups[group_key] ||= {})[suffix] = value
end
else
@env.select { |key, _| key =~ pattern }
end
end
end

# Run the generator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ rails:
db:
host: <%= env('POSTGRES_HOST') %>
port: <%= env('POSTGRES_PORT') %>
velorum:
enabled: <%= env_set?('VELORUM_ENABLED') ? env('VELORUM_ENABLED') : env('COMPOSE_PROFILES').include?('ide_velorum') %>
host: <%= env('VELORUM_HOST') %>:<%= env('VELORUM_PORT') %>
jwt_secret: <%= env('VELORUM_JWT_SECRET') %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
<% find_envs(/VELORUM_MODEL_(\S+?)_.+/, group: true).each_with_index do |(_, envs), i| %>
<%= ',' if i > 0 %>
{
"identifier": "<%= envs.fetch('IDENTIFIER', '') %>",
"name": "<%= envs.fetch('NAME', '') %>",
"capabilities": [
<%= envs.fetch('CAPABILITIES', '').split(',').map { |c| "\"#{c}\"" }.join(',') %>
],
"provider": "<%= envs.fetch('PROVIDER', '') %>",
"api": "<%= envs.fetch('API', '') %>",
"auth": "<%= envs.fetch('AUTH', '') %>",
"token_cost": <%= envs.fetch('TOKEN_COST', '').to_f %>
}
<% end %>
]
27 changes: 27 additions & 0 deletions container/velorum/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ARG PYTHON_VERSION=3.12
ARG UV_VERSION=0.11.16

FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
FROM python:${PYTHON_VERSION}-slim

COPY --from=uv /uv /uvx /usr/local/bin/

WORKDIR /velorum

COPY projects/velorum/pyproject.toml projects/velorum/uv.lock ./
RUN uv sync --frozen
COPY projects/velorum/src/model.py ./src/model.py
RUN uv run python -c "from src.model import load_vector_model; load_vector_model()"

COPY projects/velorum/cli ./cli
COPY projects/velorum/src ./src
COPY projects/velorum/main.py ./main.py

ENV HF_HUB_OFFLINE=1
ENV PYTHONUNBUFFERED=1

HEALTHCHECK --interval=5s --timeout=3s --retries=3 \
CMD uv run python -c "import grpc; from grpc_health.v1 import health_pb2, health_pb2_grpc; ch = grpc.insecure_channel('localhost:50051'); stub = health_pb2_grpc.HealthStub(ch); stub.Check(health_pb2.HealthCheckRequest(service='liveness'))" || exit 1

EXPOSE 50051
CMD ["uv", "run", "main.py"]
15 changes: 15 additions & 0 deletions docker-compose/.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,28 @@ DRACO_REST_AQUILA_TOKEN=draco-rest
DRACO_CRON_AQUILA_TOKEN=draco-cron

# Active services
# Available services: ide, runtime, ide_velorum (AI orchestrator)
COMPOSE_PROFILES=ide,runtime

# Image config
IMAGE_REGISTRY=registry.gitlab.com/code0-tech/packages
IMAGE_TAG=
IMAGE_EDITION= # ce or ee

# Velorum config
# VELORUM_ENABLED=false (override, default checks if COMPOSE_PROFILES contains ide_velorum)
VELORUM_HOST=velorum
VELORUM_PORT=50051
VELORUM_JWT_SECRET=088cfc7a7fc2b07696d8ee5e1ea9d642 # change to a random value

# example, GPT5 in the variable name can be changed to other values. This set of variables can be repeated multiple times
# VELORUM_MODEL_GPT5_IDENTIFIER=gpt-5
# VELORUM_MODEL_GPT5_NAME=GPT 5
# VELORUM_MODEL_GPT5_CAPABILITIES=explain,generate
# VELORUM_MODEL_GPT5_API= # if using a non-default base-url
# VELORUM_MODEL_GPT5_AUTH= # authentication token
# VELORUM_MODEL_GPT5_TOKEN_COST=1

# Internal config options
SAGITTARIUS_RAILS_HOST=sagittarius-rails-web
SAGITTARIUS_RAILS_PORT=3000
Expand Down
18 changes: 18 additions & 0 deletions docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@ services:
profiles:
- ide

velorum:
image: ${IMAGE_REGISTRY}/velorum:${IMAGE_TAG}
depends_on:
config-generator:
condition: service_completed_successfully
restart: unless-stopped
environment:
SECURITY_TOKEN: $VELORUM_JWT_SECRET
volumes:
- generated-configs:/tmp/generated-configs:ro
entrypoint: |
sh -c "
cp /tmp/generated-configs/velorum.models.configuration.json models.configuration.json
exec uv run main.py
"
profiles:
- ide_velorum

nginx:
image: nginx:1.31.0-alpine-slim
depends_on:
Expand Down
1 change: 1 addition & 0 deletions support/config/velorum.models.configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
15 changes: 15 additions & 0 deletions support/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,20 @@ services:
- --retry-connrefused
- http://sculptor:3000/

velorum:
image: ghcr.io/code0-tech/reticulum/ci-builds/velorum:${RETICULUM_CONTAINER_VERSION}
networks:
- boot
volumes:
- ./config/velorum.models.configuration.json:/velorum/models.configuration.json
ports:
- "50052:50051"

velorum-offline:
image: ghcr.io/code0-tech/reticulum/ci-builds/velorum:${RETICULUM_CONTAINER_VERSION}
network_mode: "none"
volumes:
- ./config/velorum.models.configuration.json:/velorum/models.configuration.json

networks:
boot:
2 changes: 2 additions & 0 deletions support/download_projects
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ mkdir -p projects
download_project aquila
download_project draco
download_project sagittarius
download_project sculptor
download_project taurus
download_project velorum
1 change: 1 addition & 0 deletions versions/velorum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6f34f272aa434826459b76f315f9f33c70d969f4