From b92aee729f83d8dbde9424d7562496c4842ef5c4 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Thu, 16 Apr 2026 13:07:11 -0700 Subject: [PATCH] feat(docker): INFRA-gap-01 wire cowork-service into compose stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds cowork-service (port 4009) to docker-compose.yml with healthcheck, depends_on gates for cosmos-emulator and platform-service, env_file integration, and Traefik labels. Unblocks Phase 3 ecosystem wiring of the ByteLyst roadmap. Also adds the services/cowork-service/Dockerfile that compose builds from. Pattern mirrors services/mcp-server/Dockerfile but copies the full workspace in one step rather than enumerating every package.json, to stay resilient to workspace membership changes. Production stage runs `node dist/server.js` on :4009 with BusyBox-wget healthcheck (bundled with node:22-alpine — no apk install required). .env.example gains a Cowork-Service section documenting: - ANTHROPIC_API_KEY, RUST_RUNTIME_BIN, RUST_RUNTIME_TIMEOUT_MS - OLLAMA_URL, OLLAMA_MODELS - FEATURE_FLAGS_ENABLED The 13th clawcowork flag telemetry_enabled already ships via COMMON_FLAGS in services/platform-service/src/modules/flags/seed.ts so seed.ts was not touched. Gap: INFRA-gap-01 Verified: docker compose config (YAML validity + env substitution), pnpm -r typecheck / lint / build / test (all green), docker compose build cowork-service (image built), docker compose up -d cowork-service --no-deps --wait (Healthy), curl -fsS localhost:4009/health → {"status":"ok","service":"cowork-service",...}. Note: full-stack `docker compose up cosmos-emulator platform-service cowork-service --wait` is blocked by a pre-existing issue in services/platform-service/Dockerfile (react-native-platform-sdk prepare script fails during pnpm install --frozen-lockfile in the image build). That is outside W1 scope; cowork-service starts clean on its own and becomes Healthy when platform-service is available out-of-band. --- .env.example | 11 +++++++++ docker-compose.yml | 34 ++++++++++++++++++++++++++++ services/cowork-service/Dockerfile | 36 ++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 services/cowork-service/Dockerfile diff --git a/.env.example b/.env.example index 29ac0184..eab23eb3 100644 --- a/.env.example +++ b/.env.example @@ -81,3 +81,14 @@ FIELD_ENCRYPT_MEK_NAME=lysnr-mek # ── Product Identity ────────────────────────────────────────── DEFAULT_PRODUCT_ID=lysnrai + +# ── Cowork Service (port 4009 — Fastify bridge to Rust runtime) ─ +# cowork-service forwards auth, flags, audit, telemetry, and AI budgets to +# platform-service. The Anthropic key is only needed when running the Rust +# runtime locally via IPC; in the containerised dev stack it is optional. +ANTHROPIC_API_KEY= +RUST_RUNTIME_BIN=cowork-orchestrator +RUST_RUNTIME_TIMEOUT_MS=300000 +OLLAMA_URL=http://localhost:11434/v1 +OLLAMA_MODELS= +FEATURE_FLAGS_ENABLED=true diff --git a/docker-compose.yml b/docker-compose.yml index 9bcb4c88..6aa4bd86 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -215,6 +215,40 @@ services: timeout: 10s retries: 3 + # ── Cowork Service (Fastify bridge to Rust agent runtime) ────── + # Bridges Tauri desktop / clients and cowork-orchestrator, delegating auth, + # flags, audit, telemetry, and AI budgets to platform-service. + cowork-service: + build: + context: . + dockerfile: services/cowork-service/Dockerfile + ports: + - '4009:4009' + env_file: + - .env + environment: + - PORT=4009 + - NODE_ENV=development + - PRODUCT_ID=clawcowork + - COSMOS_ENDPOINT=https://cosmos-emulator:8081 + - PLATFORM_SERVICE_URL=http://platform-service:4003 + - EXTRACTION_SERVICE_URL=http://extraction-service:4005 + depends_on: + cosmos-emulator: + condition: service_healthy + platform-service: + condition: service_healthy + labels: + - 'traefik.enable=true' + - 'traefik.http.routers.cowork.rule=PathPrefix(`/api/cowork`)' + - 'traefik.http.services.cowork.loadbalancer.server.port=4009' + restart: unless-stopped + healthcheck: + test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4009/health'] + interval: 10s + timeout: 5s + retries: 10 + # ── Volumes ─────────────────────────────────────────────────────── volumes: azurite-data: diff --git a/services/cowork-service/Dockerfile b/services/cowork-service/Dockerfile new file mode 100644 index 00000000..9932ed0b --- /dev/null +++ b/services/cowork-service/Dockerfile @@ -0,0 +1,36 @@ +# Build context: repo root (docker compose sets context: .) +# +# cowork-service is a lightweight Fastify bridge (no Cosmos containers of its own). +# This Dockerfile mirrors services/mcp-server/Dockerfile but copies the full +# workspace in a single step rather than enumerating every package.json, which +# keeps it resilient to additions/removals of workspace members. +FROM node:22-alpine AS builder +RUN npm config set strict-ssl false \ + && npm install -g pnpm@10 +WORKDIR /app + +# Copy workspace config + lockfile for dependency resolution +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml tsconfig.base.json ./ + +# Copy full workspace sources (dev-compose; not optimised for image size) +COPY packages/ packages/ +COPY services/ services/ +COPY dashboards/ dashboards/ +COPY scripts/ scripts/ + +# Install workspace deps (no frozen lockfile — mirrors the repo's dev install flow) +RUN pnpm install --no-frozen-lockfile + +# Build only cowork-service and its workspace dependencies +RUN pnpm -r --filter @lysnrai/cowork-service... build + +# Deploy to isolated directory (production deps only) +RUN pnpm --filter @lysnrai/cowork-service deploy --legacy /app/deploy + +# ── Production ───────────────────────────────────────────── +FROM node:22-alpine +WORKDIR /app +COPY --from=builder /app/deploy ./ +ENV NODE_ENV=production +EXPOSE 4009 +CMD ["node", "dist/server.js"]