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
10 changes: 0 additions & 10 deletions .env

This file was deleted.

11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
GROQ_API_KEY=
GOOGLE_API_KEY=
SUPABASE_URL=
SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
Telegram__BotToken=
Telegram__ApiBaseUrl=http://localhost:5079
Telegram__SignupUrl=https://dualmind.arena/signup
Telegram__BattleCooldownSeconds=15
Telegram__SoftTimeoutSeconds=30
Telegram__ApiTimeoutSeconds=75
Original file line number Diff line number Diff line change
@@ -1,58 +1,59 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy ASP.Net Core app to Azure Web App - DualMind-Arena

on:
push:
branches:
- master
workflow_dispatch:

jobs:
build:
runs-on: windows-latest
permissions:
contents: read #This is required for actions/checkout

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'

- name: Build with dotnet
run: dotnet build src/DualMind.API/DualMind.API.csproj --configuration Release

- name: dotnet publish
run: dotnet publish src/DualMind.API/DualMind.API.csproj -c Release -o "${{env.DOTNET_ROOT}}/myapp"

- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
name: .net-app
path: "${{env.DOTNET_ROOT}}/myapp"

deploy:
runs-on: windows-latest
needs: build
permissions:
contents: none

steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: .net-app

- name: Deploy to Azure Web App
id: deploy-to-webapp
uses: azure/webapps-deploy@v3
with:
app-name: 'dualmind-arena'
slot-name: 'Production'
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: .
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy ASP.Net Core app to Azure Web App - DualMind-Arena

on:
push:
branches:
- main
workflow_dispatch:

jobs:
build:
runs-on: windows-latest
permissions:
contents: read #This is required for actions/checkout

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'

- name: Build with dotnet
run: dotnet build src/DualMind.API/DualMind.API.csproj --configuration Release

- name: dotnet publish
run: dotnet publish src/DualMind.API/DualMind.API.csproj -c Release -o ./publish

- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
name: .net-app
path: ./publish

deploy:
runs-on: windows-latest
needs: build
permissions:
contents: none

steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: .net-app
path: ./publish

- name: Deploy to Azure Web App
id: deploy-to-webapp
uses: azure/webapps-deploy@v3
with:
app-name: 'dualmind-arena'
slot-name: 'Production'
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }}
package: ./publish
36 changes: 0 additions & 36 deletions .github/workflows/dotnet.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Verify

on:
push:
branches: [ "master" ]
branches: [ "main" ]
pull_request:
branches: [ "master" ]
branches: [ "main" ]

jobs:
build:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ yarn-error.log

# Environment Variables
.env
.codex/

# Verification Demo
verification_demo/node_modules/
Expand Down
50 changes: 44 additions & 6 deletions ENV_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ Create a `.env` file in the project root directory with the following variables:
SUPABASE_URL=your_supabase_url_here
SUPABASE_SERVICE_KEY=your_supabase_service_key_here

# Groq API Key (REQUIRED)
GROQ_API_KEY=your_groq_api_key_here
# Groq API Key
# Keep this if you want /api/speech/generate to stay direct to Groq.
# Chat/streaming no longer need it when Cloudflare AI Gateway + BYOK are configured.
# GROQ_API_KEY=your_groq_api_key_here

# Google API Key (optional, if using Google directly outside Cloudflare)
# GOOGLE_API_KEY=your_google_api_key_here

# ============ OPTIONAL ============

Expand All @@ -27,11 +32,33 @@ GROQ_API_KEY=your_groq_api_key_here

# App Secret (NOT NEEDED - was for database key encryption)
# APP_SECRET=not_needed

# Cloudflare AI Gateway (required for chat/streaming)
# Groq + Google chat/streaming and Cloudflare Workers AI chat all route through the gateway.
# Internal DB model names stay unchanged for Groq/Google; Cloudflare Workers AI models should be stored
# exactly as their Workers AI model IDs (for example @cf/meta/llama-3.1-8b-instruct).
# CLOUDFLARE_AI_GATEWAY_ACCOUNT_ID=your_cloudflare_account_id
# CLOUDFLARE_AI_GATEWAY_ID=your_gateway_id

# Set to true only if Cloudflare is storing your provider keys (BYOK mode).
# In BYOK mode, the app sends CLOUDFLARE_AI_GATEWAY_TOKEN for chat requests instead of provider keys.
# Groq speech still uses the direct Groq API, so keep GROQ_API_KEY or DB provider keys available for speech.
# Chat and streaming are routed through Cloudflare AI Gateway and will fail fast if the gateway is not configured.
# CLOUDFLARE_AI_GATEWAY_USE_BYOK=false
# CLOUDFLARE_AI_GATEWAY_TOKEN=your_cloudflare_gateway_token

# Cloudflare Workers AI (required if you add provider_name = cloudflare models in ai_models)
# Use a Cloudflare API token with Workers AI Read access.
# CLOUDFLARE_WORKERS_AI_API_TOKEN=your_cloudflare_workers_ai_api_token

# Optional default used only if a Cloudflare Workers AI request reaches the provider without a model name.
# DEFAULT_CLOUDFLARE_WORKERS_AI_MODEL=@cf/meta/llama-3.1-8b-instruct
```

### Priority Order:
1. **Environment Variable (GROQ_API_KEY)** - Used first if set (from .env or Azure)
2. **Database Keys** - Used as fallback if no environment variable is set
1. **Cloudflare AI Gateway** - Required for chat/streaming traffic
2. **Provider Env Vars / Database Keys** - Used for Groq or Google only when the gateway path still needs direct provider auth
3. **Direct Groq Speech** - `/api/speech/generate` still uses `GROQ_API_KEY` or Groq DB keys

## Azure Deployment (Azure Secrets)

Expand All @@ -43,13 +70,24 @@ When deploying to Azure, set these as **Application Settings** or **Key Vault Se
- `SUPABASE_URL` = your_supabase_url
- `SUPABASE_SERVICE_KEY` = your_supabase_service_key

Optional AI Gateway settings:
- `CLOUDFLARE_AI_GATEWAY_ACCOUNT_ID`
- `CLOUDFLARE_AI_GATEWAY_ID`
- `CLOUDFLARE_AI_GATEWAY_USE_BYOK`
- `CLOUDFLARE_AI_GATEWAY_TOKEN`
- `CLOUDFLARE_WORKERS_AI_API_TOKEN`
- `DEFAULT_CLOUDFLARE_WORKERS_AI_MODEL`

The backend will automatically use Azure environment variables when deployed.

## Important Notes:

- **Local Development**: Use `.env` file (already in .gitignore)
- **Azure Production**: Use Azure App Service Configuration/Secrets
- The `.env` file is automatically loaded on application start
- If `GROQ_API_KEY` is set, it takes priority over database keys
- If no `GROQ_API_KEY` is set, the system will use database keys (if available)
- Chat and streaming require Cloudflare AI Gateway to be configured
- Groq and Google model names stay unchanged in the database; the backend maps them to Cloudflare-compatible names at request time
- Cloudflare Workers AI model names should be stored exactly as the official Workers AI model IDs
- If Cloudflare Workers AI models are active, set `CLOUDFLARE_WORKERS_AI_API_TOKEN`
- If Groq speech is enabled, keep `GROQ_API_KEY` or active Groq DB keys available

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS telegram_sessions (
telegram_chat_id BIGINT PRIMARY KEY,
jwt_token TEXT NOT NULL,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

ALTER TABLE telegram_sessions
ADD COLUMN IF NOT EXISTS refresh_token TEXT;

ALTER TABLE telegram_sessions
ADD COLUMN IF NOT EXISTS jwt_expires_at TIMESTAMPTZ;
Loading
Loading