Skip to content

Commit d7f7cd3

Browse files
committed
Build out deployment infrastructure (Docker, CI/CD) and fix cascading workspace deletes
1 parent 7746db1 commit d7f7cd3

4 files changed

Lines changed: 71 additions & 38 deletions

File tree

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: TLCM Engine CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- name: Set up Python 3.12
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: '3.12'
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install -e .
25+
pip install pytest pytest-asyncio
26+
27+
- name: Run tests (No GPU)
28+
env:
29+
TLCM_TEST_MODE: "1"
30+
COGNITION_BACKEND: "gemini"
31+
run: |
32+
python -m pytest tests/unit/ -v

Dockerfile

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,30 @@
1-
# Stage 1: Build the React Dashboard
2-
FROM node:20-alpine AS frontend-builder
3-
WORKDIR /web
4-
# Copy package files
5-
COPY tlcm-web/package*.json ./
6-
RUN npm install
7-
# Copy React source
8-
COPY tlcm-web/ ./
9-
RUN npm run build
10-
11-
# Stage 2: Build the Python API Backend
12-
FROM python:3.11-slim
13-
WORKDIR /app
1+
# TLCM Engine Dockerfile
2+
FROM python:3.12-slim
143

15-
# System dependencies for ChromaDB and SQLite
4+
# Install system dependencies
165
RUN apt-get update && apt-get install -y --no-install-recommends \
176
build-essential \
187
sqlite3 \
198
&& rm -rf /var/lib/apt/lists/*
209

21-
# Install Python requirements
10+
WORKDIR /app
11+
12+
# Install dependencies first for Docker caching
2213
COPY requirements.txt .
2314
RUN pip install --no-cache-dir -r requirements.txt
2415

25-
# Copy backend code
26-
COPY core/ core/
27-
COPY server/ server/
28-
COPY integrations/ integrations/
29-
COPY tlcm_client.py .
30-
COPY pyproject.toml .
16+
# Copy application source
17+
COPY . .
3118

32-
# Install as a package
33-
RUN pip install -e .
19+
# Ensure data directory exists
20+
RUN mkdir -p /app/data
3421

35-
# Copy the compiled React dashboard from Stage 1 into the place the backend expects it
36-
COPY --from=frontend-builder /web/dist /app/tlcm-web/dist
22+
# Environment configuration
23+
ENV TLCM_DATA_DIR=/app/data
24+
ENV COGNITION_BACKEND=gemini
3725

38-
# Expose the Universal API and Dashboard port
26+
# Expose API port
3927
EXPOSE 8000
4028

41-
# Set environment
42-
ENV PYTHONDONTWRITEBYTECODE=1
43-
ENV PYTHONUNBUFFERED=1
44-
# Data storage directory (can be mounted via Volume)
45-
ENV TLCM_DATA_DIR=/app/data
46-
47-
# Run the Uvicorn server seamlessly
48-
CMD ["uvicorn", "server.main:app", "--host", "0.0.0.0", "--port", "8000"]
29+
# Start server
30+
CMD ["python", "-m", "uvicorn", "server.main:app", "--host", "0.0.0.0", "--port", "8000"]

docker-compose.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,25 @@ services:
66
container_name: tlcm-engine
77
ports:
88
- "8000:8000"
9+
environment:
10+
- COGNITION_BACKEND=${COGNITION_BACKEND:-gemini}
11+
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
12+
- TLCM_CORS_ORIGINS=*
13+
- TLCM_DATA_DIR=/app/data
914
volumes:
1015
- tlcm_data:/app/data
11-
environment:
12-
# Inject your Google Gemini API key to activate the biological processing engine
13-
- GEMINI_API_KEY=${GEMINI_API_KEY}
1416
restart: unless-stopped
1517

18+
# Optional local Ollama if air-gapped deployment is preferred
19+
# Expose it here to the TLCM Engine directly
20+
# ollama:
21+
# image: ollama/ollama
22+
# ports:
23+
# - "11434:11434"
24+
# volumes:
25+
# - ollama_data:/root/.ollama
26+
# restart: unless-stopped
27+
1628
volumes:
1729
tlcm_data:
18-
name: tlcm_persistent_memory
30+
# ollama_data:

server/routers/workspaces.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,14 @@ def delete_workspace(name: str):
4444
raise HTTPException(status_code=404, detail="Workspace not found")
4545
conn = get_connection()
4646
try:
47+
# Cascade delete explicitly to avoid FOREIGN KEY constraint failure
48+
conn.execute("PRAGMA foreign_keys=OFF")
49+
conn.execute("DELETE FROM temporal_jumps WHERE workspace_id=?", (ws["id"],))
50+
conn.execute("DELETE FROM cross_workspace_links WHERE source_workspace_id=? OR target_workspace_id=?", (ws["id"], ws["id"]))
51+
conn.execute("DELETE FROM memories WHERE workspace_id=?", (ws["id"],))
52+
conn.execute("DELETE FROM epochs WHERE workspace_id=?", (ws["id"],))
4753
conn.execute("DELETE FROM workspaces WHERE id=?", (ws["id"],))
54+
conn.execute("PRAGMA foreign_keys=ON")
4855
conn.commit()
4956
return {"status": "deleted", "workspace": name}
5057
finally:

0 commit comments

Comments
 (0)