# Vendored from Talon-Studio docker-compose.release.yml. On talonlabs.dev, re-vendor
# rather than edit; once downloaded, this file is yours to edit.
#
# This is the file https://talonlabs.dev/docs/install and
# https://talonlabs.dev/studio/install.sh fetch. Re-vendor with:
#
#   STUDIO_REPO=../Talon-Studio pnpm vendor:studio
#
# Comment references to docs/operators/*.md point at the product's operator
# docs; https://talonlabs.dev/docs covers everything an install needs.
#
# upstream-commit: 25272205f53304c3adf285c1e3e53be7f1acfcf2
# upstream-file:   docker-compose.release.yml
# body-sha256:     d3a5f306027fa2c71d5d675c8e293b8eae48bd769e6ed1699785943c93862050
# --- vendored content follows; everything below is a copy ---
# Example customer compose — pull a published image, mount /data, set env vars.
# See docs/operators/deploy.md and docs/operators/environment-variables.md.
name: talon-studio

services:
  app:
    image: ${TALON_STUDIO_IMAGE:-ghcr.io/talon-labs-detection-platform/talon-studio:v1.0.2-beta}
    init: true
    ports:
      # Loopback only. Put a reverse proxy that terminates TLS in front
      # (docs/operators/secure-your-deployment.md); publishing on every
      # interface would serve the sign-in page over plain HTTP to the network.
      - "127.0.0.1:${TALON_HTTP_PORT:-3000}:3000"
    env_file:
      # Also carries CLAUDE_CODE_OAUTH_TOKEN or CODEX_ACCESS_TOKEN when the AI
      # provider is Claude Code or Codex (subscription) — see
      # docs/operators/environment-variables.md.
      - .env
    environment:
      # Talon Labs' licence API. Called only once an Enterprise key is stored
      # (a Community key never calls it); set TALON_LICENSE_API_URL= (empty) in
      # .env to make no licence calls at all. The update check (a GET of
      # https://www.talonlabs.dev/releases.json) is separate:
      # TALON_DISABLE_UPDATE_CHECK=true in .env turns it off.
      - TALON_LICENSE_API_URL=${TALON_LICENSE_API_URL-https://www.talonlabs.dev/api/license}
      # Spoken replies come from the kokoro service below. Set TALON_TTS_URL=
      # (empty) in .env to turn the server voice off; the browser's built-in
      # voice reads replies instead.
      - TALON_TTS_URL=${TALON_TTS_URL-http://kokoro:8880}
    security_opt:
      - no-new-privileges:true
    volumes:
      - talon_data:/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    restart: unless-stopped

  # The assistant's voice: the Kokoro-82M model Studio has always spoken with,
  # served by its upstream image. It runs beside the app rather than inside it
  # because Kokoro's phonemiser includes eSpeak NG (GPL-3.0-or-later). Your
  # machine pulls this image from its publisher, unmodified, so the Studio image
  # carries none of it. Pinned by digest. Weights are baked in: nothing to keep,
  # no volume. Publishes no port; the app reaches it on the compose network.
  kokoro:
    image: ghcr.io/remsky/kokoro-fastapi-cpu:v0.8.1@sha256:28d6f0b6e4df369559012578299d201b855a08fac466f616653edd1f08c5370a
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request;urllib.request.urlopen('http://127.0.0.1:8880/health')"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 120s
    restart: unless-stopped

volumes:
  talon_data:
