-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
228 lines (207 loc) · 14 KB
/
.env.example
File metadata and controls
228 lines (207 loc) · 14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# Discord bot credentials (required)
DISCORD_TOKEN= # Discord bot token
DISCORD_CLIENT_ID= # Discord application client ID
DISCORD_GUILD_IDS= # Preferred: comma-separated Discord server (guild) IDs for slash-command deployment
DISCORD_GUILD_ID= # Legacy fallback: single Discord server (guild) ID
DISCORD_USER_ID= # Discord user ID granted privileged access (owner-only actions, rate-limit bypass)
DISCORD_SUPERUSER_IDS= # Optional comma-separated Discord user IDs allowed to review incidents; falls back to DISCORD_USER_ID when unset
OPENAI_API_KEY= # Optional when using only Ollama-backed text profiles
OLLAMA_BASE_URL= # Optional Ollama endpoint (local daemon or cloud URL)
OLLAMA_API_KEY= # Optional for Ollama cloud endpoints that require auth
OLLAMA_LOCAL_INFERENCE_ENABLED=false # Set true to allow localhost/loopback Ollama targets; leave false for cloud-only Ollama setups
LITESTREAM_REPLICA_URL= # Optional S3-compatible replica URL for backend SQLite backup replication (used by deploy/litestream.yml)
# Optional VoltOps tracing for VoltAgent runtime observability
# Enable by setting both keys together; leave both empty to keep tracing disabled.
# Get these from VoltOps project settings (console.voltagent.dev -> Settings -> Projects -> <project>).
# Note: Settings -> MCP is for MCP tokens, not these runtime project keys.
# Fly deploy note: set these on the backend Fly app (the machine running packages/backend/src/server.ts).
VOLTAGENT_PUBLIC_KEY=
VOLTAGENT_SECRET_KEY=
# Logging verbosity (debug, info, warn, error)
NODE_ENV=development
LOG_DIR=logs
LOG_LEVEL=debug
# HMAC secret for pseudonymizing Discord identifiers
# Auto-generated on local backend boot when left empty and .env exists.
# Manual generation option: node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"
INCIDENT_PSEUDONYMIZATION_SECRET=
# Optional incident/breaker alert routing
# Discord target (bot token + channel required when enabled)
INCIDENT_ALERTS_DISCORD_ENABLED=false
INCIDENT_ALERTS_DISCORD_BOT_TOKEN=
INCIDENT_ALERTS_DISCORD_CHANNEL_ID=
INCIDENT_ALERTS_DISCORD_ROLE_ID= # Optional role mention for incident alerts
# Admin email target over SMTP (host/from/to required when enabled)
INCIDENT_ALERTS_EMAIL_ENABLED=false
INCIDENT_ALERTS_EMAIL_SMTP_HOST=
INCIDENT_ALERTS_EMAIL_SMTP_PORT=587
INCIDENT_ALERTS_EMAIL_SMTP_SECURE=false
INCIDENT_ALERTS_EMAIL_SMTP_USERNAME=
INCIDENT_ALERTS_EMAIL_SMTP_PASSWORD=
INCIDENT_ALERTS_EMAIL_FROM=
INCIDENT_ALERTS_EMAIL_TO= # Comma-separated recipient list
# Optional prompt configuration overrides
# Provide a path to a YAML file (copy packages/prompts/src/defaults.yaml) to tweak shared base prompts for both backend and Discord bot runtimes without redeploying.
PROMPT_CONFIG_PATH=
# Optional bot profile vendoring overrides
BOT_PROFILE_ID=footnote # Stable profile key for this bot runtime
BOT_PROFILE_DISPLAY_NAME=Footnote # Human-readable profile name used by this runtime
BOT_PROFILE_PROMPT_OVERLAY= # Optional inline profile overlay text (takes precedence over path)
BOT_PROFILE_PROMPT_OVERLAY_PATH= # Optional path to a UTF-8 text file with overlay instructions. Templates: packages/prompts/src/profile-overlays/danny.md or packages/prompts/src/profile-overlays/myuri.md
BOT_PROFILE_MENTION_ALIASES= # Optional comma-separated plaintext aliases for this bot profile, e.g. ari
FLY_APP_NAME=
# Optional rate limiting overrides
RATE_LIMIT_USER=true
USER_RATE_LIMIT=5
USER_RATE_WINDOW_MS=60000
RATE_LIMIT_CHANNEL=true
CHANNEL_RATE_LIMIT=10
CHANNEL_RATE_WINDOW_MS=60000
RATE_LIMIT_GUILD=true
GUILD_RATE_LIMIT=20
GUILD_RATE_WINDOW_MS=60000
# Optional web API rate limiting configuration
# These limits are stricter than Discord limits to prevent abuse of the public web endpoint
WEB_API_RATE_LIMIT_IP=3 # Maximum requests per IP per time window (default: 3)
WEB_API_RATE_LIMIT_IP_WINDOW_MS=60000 # Time window for IP rate limiting in milliseconds (default: 60000)
WEB_API_RATE_LIMIT_SESSION=5 # Maximum requests per session per time window (default: 5)
WEB_API_RATE_LIMIT_SESSION_WINDOW_MS=60000 # Time window for session rate limiting in milliseconds (default: 60000)
# Cloudflare Turnstile CAPTCHA configuration (optional for web reflect API)
# Get these from https://dash.cloudflare.com/profile/api-tokens
# Public site key is served to the web app via /config.json (requires secret key to enable)
TURNSTILE_SITE_KEY=
TURNSTILE_ALLOWED_HOSTNAMES= # Optional comma-separated public hostnames allowed in successful Turnstile verification responses. When unset, backend falls back to request host/origin. Recommended in production, e.g. ai.jordanmakes.dev
TURNSTILE_SECRET_KEY= # Secret key for server-side verification (never expose publicly)
# Optional thread engagement controls
ALLOW_THREAD_RESPONSES=true # Set false to block replies in all threads unless in whitelist (ALLOWED_THREAD_IDS)
ALLOWED_THREAD_IDS= # Comma-separated thread IDs that stay enabled when thread replies are disabled
BOT_BACK_AND_FORTH_LIMIT=2 # How many consecutive bot-visible replies to allow before backing off
BOT_BACK_AND_FORTH_COOLDOWN_MS=300000 # Cooldown after hitting the back-and-forth limit
BOT_BACK_AND_FORTH_TTL_MS=600000 # How long a back-and-forth streak stays relevant
BOT_BACK_AND_FORTH_ACTION=react # Either "react" or "ignore" when the limit is reached
BOT_BACK_AND_FORTH_REACTION=👀 # Reaction used when BOT_BACK_AND_FORTH_ACTION=react
BOT_DIRECT_INVOCATION_MIN_THRESHOLD=0.75 # Minimum score required before answering a bot-authored direct mention or reply
CATCHUP_AFTER_MESSAGES=10 # Catch up automatically after this many unseen channel messages
CATCHUP_IF_MENTIONED_AFTER_MESSAGES=5 # Lower catch-up threshold when the bot is mentioned
STALE_COUNTER_TTL_MS=3600000 # How long stale engagement counters stay valid
# Optional image generation overrides
IMAGE_DEFAULT_TEXT_MODEL=gpt-4.1-mini
IMAGE_DEFAULT_IMAGE_MODEL=gpt-image-1-mini
IMAGE_DEFAULT_QUALITY=low
IMAGE_DEFAULT_OUTPUT_FORMAT=png
IMAGE_DEFAULT_OUTPUT_COMPRESSION=100
IMAGE_TOKENS_PER_REFRESH=10
IMAGE_TOKEN_REFRESH_INTERVAL_MS=86400000
# Provide a JSON map for convenience when tweaking several models at once
IMAGE_MODEL_MULTIPLIERS={"gpt-image-1-mini":1,"gpt-image-1":2,"gpt-image-1.5":2}
# Or override individual models by replacing hyphens with underscores
IMAGE_MODEL_MULTIPLIER_GPT_IMAGE_1=2
IMAGE_MODEL_MULTIPLIER_GPT_IMAGE_1_MINI=1
IMAGE_MODEL_MULTIPLIER_GPT_IMAGE_1_5=2
# Optional channel context manager configuration
# Enable in-memory per-channel state tracking for engagement decisions and cost monitoring
CONTEXT_MANAGER_ENABLED=true # Enables rolling message buffers and metrics
CONTEXT_MANAGER_MAX_MESSAGES=50 # Number of recent messages to keep per channel
CONTEXT_MANAGER_RETENTION_MS=3600000 # How long to keep messages (1 hour = 3600000ms)
CONTEXT_MANAGER_EVICTION_INTERVAL_MS=300000 # Cleanup frequency (5 minutes = 300000ms)
# Optional realtime engagement filter configuration
# Enable context-aware engagement scoring to replace simple counter-based catchup
REALTIME_FILTER_ENABLED=true # Set true to enable weighted engagement scoring
# Engagement scoring weights (used only when REALTIME_FILTER_ENABLED=true)
# Each signal produces a 0-1 score; these weights scale them before summing.
ENGAGEMENT_WEIGHT_MENTION=0.3 # Full score for @mentions/replies; slightly lower for plaintext bot name/nickname mentions.
ENGAGEMENT_WEIGHT_QUESTION=0.2 # Rewards question marks, interrogative words, and common question phrases.
ENGAGEMENT_WEIGHT_TECHNICAL=0.15 # Scales with how many technical keywords appear in the message.
ENGAGEMENT_WEIGHT_HUMAN_ACTIVITY=0.15 # Boosts when recent messages are mostly from humans (neutral if no metrics).
ENGAGEMENT_WEIGHT_BOT_NOISE=0.05 # Inverted bot-message share; more bot chatter lowers engagement.
ENGAGEMENT_WEIGHT_DM_BOOST=1.5 # If this is a DM, multiply the final score by this value
ENGAGEMENT_WEIGHT_DECAY=0.05 # Reserved for time-decay of older signals; not applied yet.
# Engagement behavior preferences
ENGAGEMENT_IGNORE_MODE=silent # When skipping engagement, either stay "silent" or "react" with an emoji.
ENGAGEMENT_REACTION_EMOJI=👍 # Emoji reaction used when ignoreMode=react.
ENGAGEMENT_MIN_THRESHOLD=0.5 # Engage only if the final score is >= this threshold.
ENGAGEMENT_PROBABILISTIC_LOW=0.4 # Lower bound (inclusive) of the optional LLM refinement band.
ENGAGEMENT_PROBABILISTIC_HIGH=0.6 # Upper bound (inclusive) of the optional LLM refinement band.
ENGAGEMENT_ENABLE_LLM_REFINEMENT=false # Enables refinement pass (currently a no-op stub).
DISCORD_BOT_LOG_FULL_CONTEXT=false # Enable only when debugging large-context behavior
# Optional web server configuration
# Canonical local backend origin for bot API calls and the web Vite dev proxy target
DATA_DIR=/data # Persistent backend data directory
HOST=:: # Host/interface the backend server binds to
PORT=3000 # Port the backend server listens on
BACKEND_BASE_URL="http://localhost:3000"
BACKEND_REQUEST_TIMEOUT_MS=180000 # Bot -> backend reflect timeout budget (3 minutes by default)
WEBHOOK_PORT=3001 # Local webhook listener port used by the Discord bot; keep this different from PORT
WEB_BASE_URL=http://localhost:8080 # Base URL for the web server that hosts trace pages
WEB_TRUST_PROXY=false # Set true only when a reverse proxy sets X-Forwarded-For correctly.
ALLOWED_ORIGINS=https://ai.jordanmakes.dev # Production CORS allowlist. Add localhost entries only for local development.
# DEV example: ALLOWED_ORIGINS=http://localhost:8080,http://localhost:3000,https://ai.jordanmakes.dev
FRAME_ANCESTORS='self',https://ai.jordanmakes.dev # Production CSP frame-ancestors allowlist. Add localhost entries only for local development.
# DEV example: FRAME_ANCESTORS='self',https://ai.jordanmakes.dev,http://localhost:8080,http://localhost:3000
DEFAULT_MODEL=gpt-5-mini # Default model for reflect responses
MODEL_PROFILE_CATALOG_PATH= # Optional YAML path for backend model profile catalog (defaults to bundled catalog)
DEFAULT_PROFILE_ID=openai-text-medium # Default response model profile ID used when planner does not select a valid profile
PLANNER_PROFILE_ID=openai-text-fast # Planner model profile ID (can differ from DEFAULT_PROFILE_ID)
PLANNER_STRUCTURED_OUTPUT_ENABLED=true # Use structured planner function-calling output when available
PLANNER_ALLOW_TEXT_JSON_COMPATIBILITY_FALLBACK=false # Allow planner text JSON compatibility fallback when structured execution is unavailable or fails
REALTIME_DEFAULT_MODEL=gpt-realtime-mini # Default model for realtime voice sessions
REALTIME_DEFAULT_VOICE=echo # Default voice for realtime voice sessions
REALTIME_TURN_DETECTION=server_vad # server_vad or semantic_vad for realtime voice turns
# Optional realtime VAD tuning (leave unset to use provider defaults)
# REALTIME_VAD_THRESHOLD=0.5 # 0-1 server VAD threshold
# REALTIME_VAD_SILENCE_MS=600 # server VAD silence duration before turn ends
# REALTIME_VAD_PREFIX_MS=200 # server VAD prefix padding in milliseconds
# REALTIME_VAD_CREATE_RESPONSE=true # auto-create response after a detected turn
# REALTIME_VAD_INTERRUPT_RESPONSE=false # allow new speech to interrupt a response
# REALTIME_VAD_EAGERNESS=auto # semantic VAD eagerness: low|medium|high|auto
REALTIME_GREETING=Hey, {bot} here. # greeting text (supports {bot})
DEFAULT_REASONING_EFFORT=low
DEFAULT_VERBOSITY=low
OPENAI_REQUEST_TIMEOUT_MS=180000 # Backend OpenAI request timeout budget (3 minutes by default)
CHAT_WORKFLOW_MODE_ID=grounded # Workflow mode id: fast, balanced, or grounded
TRACE_API_TOKEN= # Shared secret required for POST /api/traces (generate with: node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))")
REFLECT_SERVICE_TOKEN= # Optional shared secret for trusted server-side callers of POST /api/reflect
TRACE_API_RATE_LIMIT=10 # Max trace writes per IP per window
TRACE_API_RATE_LIMIT_WINDOW_MS=60000
REFLECT_SERVICE_RATE_LIMIT=30 # Max trusted-service reflect requests per IP per window
REFLECT_SERVICE_RATE_LIMIT_WINDOW_MS=60000
TRACE_API_MAX_BODY_BYTES=262144 # Max POST body size for /api/traces (256 KB)
REFLECT_API_MAX_BODY_BYTES=262144 # Max POST body size for /api/reflect (256 KB)
# Optional Execution Contract TrustGraph advisory retrieval wiring
# This repo contains backend integration only; external TrustGraph service/runtime is separate.
# Safe default: keep disabled.
EXECUTION_CONTRACT_TRUSTGRAPH_ENABLED=false
# Emergency rollback switch for external retrieval while keeping local chat behavior.
EXECUTION_CONTRACT_TRUSTGRAPH_KILL_SWITCH=false
EXECUTION_CONTRACT_TRUSTGRAPH_POLICY_ID=server_chat_runtime_policy
EXECUTION_CONTRACT_TRUSTGRAPH_TIMEOUT_MS=800
EXECUTION_CONTRACT_TRUSTGRAPH_MAX_CALLS=1
# Adapter modes: none | stub | http
EXECUTION_CONTRACT_TRUSTGRAPH_ADAPTER_MODE=none
# Stub mode is for local/dev/test only.
EXECUTION_CONTRACT_TRUSTGRAPH_STUB_ADAPTER_MODE=success
# Required when ENABLED=true and ADAPTER_MODE=http.
EXECUTION_CONTRACT_TRUSTGRAPH_ADAPTER_ENDPOINT_URL=
EXECUTION_CONTRACT_TRUSTGRAPH_ADAPTER_API_TOKEN=
# Optional adapter-side config selector/header.
EXECUTION_CONTRACT_TRUSTGRAPH_ADAPTER_CONFIG_REF=
# Ownership binding modes: none | http
EXECUTION_CONTRACT_TRUSTGRAPH_OWNERSHIP_BINDING_MODE=none
EXECUTION_CONTRACT_TRUSTGRAPH_OWNERSHIP_VALIDATOR_ID=backend_tenancy_http_v1
# Required only when OWNERSHIP_BINDING_MODE=http.
EXECUTION_CONTRACT_TRUSTGRAPH_OWNERSHIP_ENDPOINT_URL=
EXECUTION_CONTRACT_TRUSTGRAPH_OWNERSHIP_API_TOKEN=
# Optional Cloudinary configuration (image uploads)
# If unset, image responses fall back to Discord attachments.
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
# GitHub webhook configuration for blog integration (optional; enables blog sync)
GITHUB_WEBHOOK_SECRET= # The secret configured in GitHub repository webhook settings, used to verify webhook signatures from GitHub Discussions
GITHUB_WEBHOOK_REPOSITORY=footnote-ai/footnote # Only accept webhook deliveries for this repository
GITHUB_WEBHOOK_MAX_BODY_BYTES=262144 # Max POST body size for the GitHub webhook endpoint (256 KB)
# SQLite database path
# On Fly.io, /data is backed by a persistent volume (see deploy/fly.backend.toml)
# For bare metal or other deployments, use any persistent path
PROVENANCE_SQLITE_PATH=/data/provenance.db
INCIDENT_SQLITE_PATH=/data/incidents.db